Skip to content

Latest commit

 

History

History
244 lines (185 loc) · 7.59 KB

docker.md

File metadata and controls

244 lines (185 loc) · 7.59 KB

Run Sikio with Docker

This guide runs the Sikio image with Docker Compose on a Linux host, behind Caddy. Caddy obtains the TLS certificate. The last steps claim the instance and register your passkey. Operations documents every setting.

What you need

  • A Linux host, amd64 or arm64, with Docker Engine and the Compose plugin.
  • A domain name that resolves to the host, for example sikio.example.org. Passkeys are bound to the domain they are created on, so use the final domain from the start.
  • Caddy on the same host, or another reverse proxy that terminates TLS and supports WebSockets.

The image is ghcr.io/oliverandrich/sikio. Each version is tagged X.Y.Z, X.Y and latest. The X.Y tag receives patch releases, which contain no migrations. A new minor version may contain migrations. Switch to it by changing the tag manually.

1. Lay out the directory

mkdir -p /opt/sikio && cd /opt/sikio
curl -fsSLO https://raw.githubusercontent.com/oliverandrich/sikio/main/docs/compose.yaml

compose.yaml runs the image with SQLite and stores its data in the volume sikio-data. It publishes the port on the loopback only, for Caddy. Set PHX_HOST to your domain.

2. Write the environment file

SECRET_KEY_BASE signs sessions. Never change it after the first start.

umask 077
printf 'SECRET_KEY_BASE=%s\n' "$(openssl rand -base64 48 | tr -d '\n')" > sikio.env

Add further settings to the same file, one NAME=value per line. See Operations. Keep sikio.env out of version control. On a small host, these two settings lower memory use:

printf 'ERL_AFLAGS=+S 2:2\nRELEASE_MODE=interactive\n' >> sikio.env

Operations explains what they do.

3. Start it

docker compose up -d
docker compose logs -f sikio

On the first start, the migration creates the SQLite database. The log line Running SikioWeb.Endpoint means the server accepts requests. Check it from the host:

curl -fsS http://127.0.0.1:4000/health

4. Put Caddy in front

sikio.example.org {
	reverse_proxy 127.0.0.1:4000
}

Caddy obtains the certificate and sends the client address in X-Forwarded-For. Inside the container, connections come from the network gateway. That address is private, so Sikio trusts it without TRUSTED_PROXIES. Reload Caddy and open https://sikio.example.org.

5. Claim the instance

The first account requires a setup code. Issue it on the host:

docker compose exec sikio bin/setup-code

The command prints the code once. Open your domain, enter the code, choose a username and create a passkey. Save the recovery codes on the next page, which are shown only once. If the code is lost, issue a new one. See Operations for details.

Further members join through invitations. Create them under Settings, then Invitations, in the gear menu.

6. Back up

The volume holds the SQLite database and the picture cache. Stop Sikio for a consistent copy:

docker compose stop sikio
docker run --rm -v sikio_sikio-data:/data -v "$PWD":/backup busybox \
  tar -czf /backup/sikio-data-$(date +%F).tar.gz -C /data .
docker compose start sikio

The volume name is prefixed with the Compose project name. That is the directory name, here sikio. docker volume ls lists it. Keep sikio.env with the backup. With a different SECRET_KEY_BASE, all existing sessions become invalid.

7. Update

Read the version's entry in the changelog first. Back up, then:

docker compose pull
docker compose up -d
docker compose logs -f sikio

The new version migrates the database on start. For a new minor version, change the tag in compose.yaml before pulling. To go back, restore the backup. An older version does not revert a newer version's migrations.

With PostgreSQL

Sikio migrates a PostgreSQL database but does not create it. Create the database and its owner before the first start.

Its own database container

Add a database service and set Sikio's DATABASE_URL to it. On an empty volume, the postgres image creates the database named in POSTGRES_DB. In compose.yaml:

services:
  sikio:
    # as before, plus:
    environment:
      SIKIO_DATABASE: postgres
      DATABASE_URL: ecto://sikio:${POSTGRES_PASSWORD}@db/sikio
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:18
    restart: unless-stopped
    environment:
      POSTGRES_USER: sikio
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: sikio
    volumes:
      - sikio-db:/var/lib/postgresql
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "sikio"]
      interval: 10s

volumes:
  sikio-data:
  sikio-db:

Set POSTGRES_PASSWORD= to a long random value in a file .env beside compose.yaml. Compose reads it to substitute ${…}. Sikio's volume then holds only the picture cache. Back up the database with pg_dump:

docker compose exec db pg_dump -U sikio sikio | gzip > sikio-$(date +%F).sql.gz

A shared database and Caddy on Docker networks

A host may run one PostgreSQL server and one Caddy for several services. Each is attached to its own Docker network. Here the database server is postgres on the network db. Caddy is on the network caddy and reads its configuration from container labels. The administrator creates a database and an owner for Sikio:

CREATE ROLE sikio LOGIN PASSWORD '…';
CREATE DATABASE sikio OWNER sikio;

Sikio is attached to both networks and publishes no port:

services:
  sikio:
    image: ghcr.io/oliverandrich/sikio:0.1
    restart: unless-stopped
    env_file: sikio.env
    environment:
      PHX_HOST: sikio.example.org
      SIKIO_DATABASE: postgres
      DATABASE_URL: ecto://sikio:${SIKIO_DB_PASSWORD}@postgres/sikio
    labels:
      caddy: sikio.example.org
      caddy.reverse_proxy: "{{upstreams 4000}}"
    networks: [db, caddy]
    volumes:
      - sikio-data:/data

volumes:
  sikio-data:

networks:
  db:
    external: true
  caddy:
    external: true

Caddy connects from its private address on the caddy network, which needs no TRUSTED_PROXIES. The volume holds only the picture cache. Sikio downloads missing pictures again. Database backups are the administrator's responsibility. Issue the setup code as in step 5.

Switch between SQLite and PostgreSQL

Operations describes the conversion. In a container, run the command in a one-off container of the sikio service while the server is stopped. Back up first.

From SQLite to PostgreSQL, add the database service as in Its own database container, but leave the sikio service on SQLite. Then convert:

docker compose stop sikio
docker compose up -d --wait db
read -rs TARGET_DATABASE_URL    # ecto://sikio:PASSWORD@db/sikio
export TARGET_DATABASE_URL
docker compose run --rm -e TARGET_DATABASE_URL sikio /app/bin/convert-to-postgres

-e TARGET_DATABASE_URL without a value passes the variable from the shell, so the password stays off the command line.

Then add SIKIO_DATABASE and DATABASE_URL to the sikio service and run docker compose up -d.

From PostgreSQL to SQLite, convert into a new file in the volume:

docker compose stop sikio
docker compose run --rm sikio /app/bin/convert-to-sqlite /data/sikio.db

The image sets DATABASE_PATH=/data/sikio.db. If an older file exists there, move it away first. The command never writes over a file. Then remove SIKIO_DATABASE and DATABASE_URL from the sikio service and run docker compose up -d.