diff --git a/HOSTING.md b/HOSTING.md new file mode 100644 index 00000000..7e218363 --- /dev/null +++ b/HOSTING.md @@ -0,0 +1,334 @@ +## Self-hosting Ozone + +Self-hosting Ozone enables you to participate as a labeler in Bluesky's system for stackable moderation. The Ozone service consists of a web UI, a backend, and a Postgres database. + +### Preparation for self-hosting Ozone + +## Create a Bluesky labeler service account + +> [!IMPORTANT] +> Before setting up your Ozone service you should create a _new_ account on the network, separate from your main account. This is the account that subscribers to your labeler will interact with: accounts for labelers appear different in Bluesky than normal accounts. + +You can create a new service account for your labeler at [bsky.app](https://bsky.app/). + +## Launch a server + +Launch a server on any cloud provider, [Digital Ocean](https://digitalocean.com/) and [Vultr](https://vultr.com/) are two popular choices. + +Ensure that you can ssh to your server and have root access. + +**Server Requirements** + +- Public IPv4 address +- Public DNS name +- Public inbound internet access permitted on port 80/tcp and 443/tcp + +**Server Recommendations** +| | | +| ---------------- | ------------ | +| Operating System | Ubuntu 22.04 | +| Memory (RAM) | 2+ GB | +| CPU Cores | 2+ | +| Storage | 40+ GB SSD | +| Architectures | amd64, arm64 | + +**Note:** It is a good security practice to restrict inbound ssh access (port 22/tcp) to your own computer's public IP address. You can check your current public IP address using [ifconfig.me](https://ifconfig.me/). + +### Open your cloud firewall for HTTP and HTTPS + +One of the most common sources of misconfiguration is not opening firewall ports correctly. Please be sure to double check this step. + +In your cloud provider's console, the following ports should be open to inbound access from the public internet. + +- 80/tcp (Used only for TLS certification verification) +- 443/tcp (Used for all application requests) + +**Note:** there is no need to set up TLS or redirect requests from port 80 to 443 because the Caddy web server, included in the Docker compose file, will handle this for you. + +### Configure DNS for your domain + +From your DNS provider's control panel, set up a domain with records pointing to your server. + +| Name | Type | Value | TTL | +| ------------- | ---- | ------------- | --- | +| `example.com` | `A` | `12.34.56.78` | 600 | + +**Note:** + +- Replace `example.com` with your domain name. +- Replace `12.34.56.78` with your server's IP address. +- Some providers may use the `@` symbol to represent the root of your domain. +- The TTL can be anything but 600 (10 minutes) is reasonable + +> [!TIP] +> Since you have your own domain, you may consider using it to setup a [custom handle](https://bsky.social/about/blog/4-28-2023-domain-handle-tutorial) for the new labeler account you created in step 1. This helps users verify who operates your labeler, and makes it more difficult to impersonate your labeler. It also just looks nice! + +### Check that DNS is working as expected + +Use a service like [DNS Checker](https://dnschecker.org/) to verify that you can resolve domain names. + +Check the following: + +- `example.com` (record type `A`) + +This should return your server's public IP. + +### Installing manually on Ubuntu 22.04 + +#### Open ports on your Linux firewall + +If your server is running a Linux firewall managed with `ufw`, you will need to open these ports: + +```bash +$ sudo ufw allow 80/tcp +$ sudo ufw allow 443/tcp +``` + +#### Install Docker + +On your server, install Docker CE (Community Edition), using the the following instructions. For other operating systems you may reference the [official Docker install guides](https://docs.docker.com/engine/install/). + +**Note:** All of the following commands should be run on your server via ssh. + +##### Uninstall old versions + +```bash +sudo apt-get remove docker docker-engine docker.io containerd runc +``` + +##### Set up the repository + +```bash +sudo apt-get update +sudo apt-get install \ + ca-certificates \ + curl \ + jq \ + gnupg +``` + +```bash +sudo install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg +sudo chmod a+r /etc/apt/keyrings/docker.gpg +``` + +```bash +echo \ + "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ + "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \ + sudo tee /etc/apt/sources.list.d/docker.list > /dev/null +``` + +##### Install Docker Engine + +```bash +sudo apt-get update +``` + +```bash +sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin +``` + +##### Verify Docker Engine installation + +```bash +sudo docker run hello-world +``` + +#### Set up the Ozone directory + +```bash +sudo mkdir /ozone +sudo mkdir /ozone/postgres +sudo mkdir --parents /ozone/caddy/data +sudo mkdir --parents /ozone/caddy/etc/caddy +``` + +#### Create the Caddyfile + +Be sure to replace `example.com` with your own domain. + +```bash +cat < [!TIP] +> There is a comprehensive guide for setting up your own Ozone labeler service within [HOSTING.md](./HOSTING.md). + +We offer a Dockerized setup for hosting both the Ozone UI and backend together. This allows you to run an Ozone labeler service on the network, which users of the Bluesky application can discover and opt into. There are a few requirements to get this setup: + +1. Create a "service account" for your labeler. This is the account that users will discover in the application, allowing them to subscribe to your labeler. You should _not_ use your personal account as an Ozone labeler service account. It can be created on [bsky.app](https://bsky.app) just like a typical account. +2. Start running the Ozone UI and backend on the public internet. The service only relies on Postgres, and is generally quite cheap and easy to run. It should be served over https at a domain that you own. +3. Associate your Ozone labeler service with your service account, and announce it to the network. Your Ozone UI will help you with this if you login to Ozone using your service account. + +This process is outlined in detail within [HOSTING.md](./HOSTING.md). + ## Contributions > While we do accept contributions, we prioritize high quality issues and pull requests. Adhering to the below guidelines will ensure a more timely review. diff --git a/service/compose.yaml b/service/compose.yaml new file mode 100644 index 00000000..eebdca08 --- /dev/null +++ b/service/compose.yaml @@ -0,0 +1,58 @@ +# @NOTE: this compose file is intended to accompany the guide found in HOSTING.md +version: '3.9' +services: + caddy: + container_name: caddy + image: caddy:2 + network_mode: host + depends_on: + - ozone + restart: unless-stopped + volumes: + - type: bind + source: /ozone/caddy/data + target: /data + - type: bind + source: /ozone/caddy/etc/caddy + target: /etc/caddy + ozone: + container_name: ozone + image: ghcr.io/bluesky-social/ozone-ui:0.1 # @TODO set initial tag + network_mode: host + restart: unless-stopped + depends_on: + postgres: + condition: service_healthy + env_file: + - /ozone/ozone.env + labels: + - 'com.centurylinklabs.watchtower.enable=true' + postgres: + container_name: postgres + image: 14.11-bookworm + network_mode: host + restart: unless-stopped + healthcheck: + test: pg_isready -h localhost -U $$POSTGRES_USER + interval: 2s + timeout: 5s + retries: 10 + volumes: + - type: bind + source: /ozone/postgres + target: /var/lib/postgresql/data + env_file: + - /ozone/postgres.env + watchtower: + container_name: watchtower + image: containrrr/watchtower:latest + network_mode: host + volumes: + - type: bind + source: /var/run/docker.sock + target: /var/run/docker.sock + restart: unless-stopped + environment: + WATCHTOWER_CLEANUP: true + WATCHTOWER_SCHEDULE: '@midnight' + WATCHTOWER_LABEL_ENABLE: true