Self-hosting with Docker (or Node)
Bongsu runs on any server with Docker: one container serves the app, the dashboard and the APIs and runs the
schedules, with everything in one SQLite file. It's the same code as the Cloudflare deployment
(deploy-cloudflare.md); only the runtime differs (apps/node).
What you need
- A server with Docker and Docker Compose.
- A public HTTPS address: passkeys only work over HTTPS, and Instagram downloads each post's media from it. A
domain pointing at the server is enough: the compose file's
httpsprofile runs Caddy, which gets the certificate. - The OAuth apps for the platforms you connect, as for Cloudflare (instagram-graph.md, youtube.md).
1. Settings
git clone https://github.com/NYT87/bongsu.git && cd bongsu
cp .env.example .env
Fill in .env (configuration.md explains each setting; the names are the Cloudflare ones):
PUBLIC_URL(https://bongsu.example.com) andDOMAIN(bongsu.example.com) for Caddy.SETUP_TOKEN,MEDIA_SIGNING_KEY,ENCRYPTION_KEY: long random strings (openssl rand -hex 32each).VAPID_PUBLIC_KEY,VAPID_PRIVATE_KEY,VAPID_SUBJECTfor push notifications (npx web-push generate-vapid-keys).- Optional:
BONGSU_APP_NAMEandBONGSU_THEME_COLORgive the app your own name and colour, applied when the image is built (configuration.md). DRY_RUN=1to start: every step runs and notifies, nothing is published.
2. Start
docker compose --profile https up -d --build
This builds the image from your checkout. To run a published release instead, set BONGSU_IMAGE in .env to
ghcr.io/nyt87/bongsu:<version> (0.2, 0.2.0 or latest, for amd64 and arm64), then:
docker compose pull bongsu
docker compose --profile https up -d
The published image has the default name and colours: branding (BONGSU_APP_NAME, BONGSU_THEME_COLOR) needs your
own build.
The first start creates the database (bongsu-data volume) and applies the migrations; every later start applies
new ones. Check https://<DOMAIN>/health (ok: true, no missing secrets): Docker's health check uses it too
(docker compose ps shows healthy).
Without the https profile, Bongsu listens on port 8787 (BONGSU_PORT to change it), for your own reverse proxy.
Then open https://<DOMAIN>/dashboard and sign up with the SETUP_TOKEN: you become the instance admin and create the
first workspace, and from there it's the same as on Cloudflare (Get started, OAuth apps, connections, devices).
Postgres (optional)
By default the database is one SQLite file in the bongsu-data volume, which is plenty for one person's channels.
To use Postgres instead, the postgres profile runs one next to Bongsu:
# in .env: POSTGRES_PASSWORD=<a long random string>
# DATABASE_URL=postgres://bongsu:<that password>@postgres:5432/bongsu
docker compose --profile https --profile postgres up -d --build
Or point DATABASE_URL at a Postgres you already run (any recent version; Bongsu creates its tables on first
start). databases.md compares the two and covers backups.
Email (optional)
Connection alerts can also go by email (configuration.md, MAILER). To see them without sending
real mail, the mail profile runs Mailpit, which catches every message:
# in .env: MAILER=smtp SMTP_HOST=mailpit SMTP_PORT=1025 MAIL_FROM=Bongsu <bongsu@example.com>
docker compose --profile https --profile mail up -d
Its web page is on http://localhost:8025 (on the server only). For real email, point SMTP_HOST, SMTP_PORT,
SMTP_USER and SMTP_PASS at your provider, or use MAILER=resend with RESEND_API_KEY.
Updating
git pull && docker compose --profile https up -d --build; with the published image, change BONGSU_IMAGE to the new
version (or keep latest) and run docker compose pull bongsu && docker compose --profile https up -d. Migrations run
at start. More in Updating.
Backups
docker compose exec bongsu node server.mjs backup /data/backup-$(date +%F).db makes a consistent copy while Bongsu
runs; the media and restoring are in Backups and restore.
Without Docker
Node 22 and pnpm (corepack enable):
pnpm install
pnpm --filter @bongsu/web build && pnpm --filter @bongsu/dashboard build && pnpm --filter @bongsu/node build
cd apps/node && set -a && . ../../.env && set +a && node dist/server.mjs
It reads the same settings from the environment, plus DATABASE_PATH (default data/bongsu.db) or DATABASE_URL
(Postgres), PORT (8787), HOST, MIGRATIONS_DIR and WEB_DIR (the repository's migrations/ and
packages/web/dist by default), and MEDIA_DIR for the local store.