siftlode/docs/self-hosting.md
npeter83 659e175755 feat(selfhost): one-command self-host package (epic 6d)
- docker-compose.selfhost.yml pulls the published image (forge.b1fr0st.eu/peter/siftlode) with a
  bundled Postgres — no source build on the operator's host.
- install.sh / install.ps1 generate the four required secrets (.env: POSTGRES_PASSWORD, SECRET_KEY,
  a valid Fernet TOKEN_ENCRYPTION_KEY, OAUTH_REDIRECT_URL), start the stack, and print the first-run
  setup-wizard URL. Everything else is configured in the web wizard.
- docs/self-hosting.md: the copy-paste playbook (get the files, run the installer, finish in the
  wizard, optional Google/SMTP, HTTPS/reverse-proxy, updates + backups).
- Verified end-to-end: a fresh install from the published image boots into setup mode and serves
  the wizard.
2026-06-21 01:42:18 +02:00

4 KiB

Self-hosting Siftlode

Run your own private Siftlode instance with Docker. You don't need the source code — the app runs from a prebuilt image, and everything user-facing (your admin account, Google sign-in, email) is configured in a web wizard on first start. There's no editing of config files by hand.

What you need

  • A machine with Docker and the Docker Compose plugin (Docker Desktop on Windows/macOS, or Docker Engine on Linux).
  • A few hundred MB of disk and ~1 GB RAM free.
  • Optional: a domain name + reverse proxy if you want HTTPS / public access (see below).

1. Get the files

Download these into a new, empty folder:

  • docker-compose.selfhost.yml
  • install.sh (Linux/macOS) or install.ps1 (Windows)

The app image is published at forge.b1fr0st.eu/peter/siftlode (public — no login to pull).

2. Run the installer

Linux / macOS:

chmod +x install.sh
./install.sh

Windows (PowerShell):

./install.ps1

The installer asks for the public URL where the instance will be reached (just press Enter for http://localhost:8080 to try it locally). It then:

  • generates the secrets it needs (SECRET_KEY, TOKEN_ENCRYPTION_KEY, a database password) into a local .env file — keep that file private,
  • pulls the image and starts the app + database,
  • prints the setup wizard URL, which looks like …/setup?token=….

3. Finish in the web wizard

Open the printed setup URL in your browser. The one-time token in it means only you (with access to the server logs) can run setup. Then click through:

  1. Admin account — your email + a password. This is how you'll sign in.
  2. Google sign-in (optional) — paste a Google OAuth client ID + secret to enable "Sign in with Google" and pulling your YouTube subscriptions. Skip it to use email + password only.
  3. Email / SMTP (optional) — an SMTP server so the app can send verification and notification emails. Skip it — without email, new registrations are simply approved by you (the admin) instead.
  4. Finish — the wizard disappears, the instance is now configured, and you land on the sign-in page. Log in with the admin account you just created.

That's it. You can change any of the optional settings later under the admin Configuration page.

The setup wizard only exists until you finish it. After that, the setup routes are disabled and the token is invalidated — there's no setup surface left on a configured instance.

Getting a Google OAuth client (optional)

Only needed for "Sign in with Google" / YouTube access. In the Google Cloud Console: create a project → APIs & Services → Credentials → Create credentials → OAuth client IDWeb application. Add your instance's …/auth/callback URL as an Authorized redirect URI, then copy the client ID and secret into the wizard's Google step. (Enable the YouTube Data API v3 for the project too.)

HTTPS / public access

The app is served on port 8080 over plain HTTP, which is fine for a LAN or a quick trial. For public access, put a reverse proxy (Caddy, Nginx, Traefik…) in front to terminate TLS, and set the public URL in the installer to your https://… address (this also marks the session cookie secure). If you've already run the installer, edit OAUTH_REDIRECT_URL in .env to the https callback URL and docker compose -f docker-compose.selfhost.yml up -d.

Day-to-day

# Update to the latest release
docker compose -f docker-compose.selfhost.yml pull
docker compose -f docker-compose.selfhost.yml up -d

# Logs / status
docker compose -f docker-compose.selfhost.yml logs -f api
docker compose -f docker-compose.selfhost.yml ps

# Stop
docker compose -f docker-compose.selfhost.yml down

Your data (accounts, subscriptions, playlists, the video catalog) lives in the siftlode_pgdata Docker volume — back that up to keep your instance's state. Database migrations run automatically when the app starts, so updating is just pull + up.