dsc install¶
Provisions Discourse on a dsc harden-prepared box: clones discourse_docker, renders containers/app.yml, runs launcher bootstrap && launcher start, polls for a live site, and appends a [[discourse]] entry to dsc.toml.
Phase 1 — the default single-container standalone.yml stack at the default path, targeting rootless Docker only (see Prerequisites). Not yet implemented: a rootful-Docker target, --image (base image override), and --bootstrap-admin (create the first admin account non-interactively). See spec/commands/install.md for the full design and remaining phases.
Usage¶
dsc install <name> --host <host>
[--ssh-user discourse] [--ssh-port 2227]
--email admin@example.com[,other@example.com]
[--smtp-host <host>] [--smtp-port <port>] [--smtp-user <user>] [--smtp-pass-stdin]
[--branch <git-revision>]
--ssh-user/--ssh-port default to match dsc harden's own defaults (discourse/2227), so a straight dsc harden <host> --pubkey-file … && dsc install <name> --host <host> --email … works with no extra flags in the common case.
What it does¶
- Preflight — checks RAM (hard floor 1 GB, warns below 2 GB) and free disk on
/var(hard floor 5 GB, warns below 30 GB), the same thresholdsdsc hardenuses. - Clones
discourse_dockerto/var/discourseif it isn't already there; otherwisegit pulls it. Idempotent — safe to re-run after a partial failure. - Renders
containers/app.ymlfrom a template based directly ondiscourse_docker's ownsamples/standalone.yml: Postgres + Redis + rate-limited web, ports 80 and 443 exposed,docker_managerpre-installed. SSL (Let's Encrypt) is requested unconditionally —templates/web.ssl.template.ymlandtemplates/web.letsencrypt.ssl.template.ymlare always included, withLETSENCRYPT_ACCOUNT_EMAILset to the first--email. There's no real downside to this even when DNS isn't pointed at the box yet: cert issuance just fails quietly and the site keeps serving plain HTTP, and re-runningdsc install/launcher rebuildonce DNS is ready picks the cert up with no further editing needed.DISCOURSE_HOSTNAMEandDISCOURSE_DEVELOPER_EMAILSare always set; the SMTP block is included only if--smtp-hostis given (otherwise the rendered file carries a comment noting mail is unconfigured);params.versionis set only if--branchis given (omitting it keepsdiscourse_docker's own default,tests-passed). Every substituted value is YAML single-quote-escaped, and the whole file is transported to the remote host base64-encoded — so a password or hostname containing$, backticks, or quotes can't break the shell command or the YAML structure. - Uploads it to
/var/discourse/containers/app.yml(install -m 0644, nosudo— see Prerequisites). - Runs
launcher bootstrap app && launcher start appas the plain SSH user withDOCKER_HOSTexported explicitly for the rootless socket (nosudo), streaming a live spinner with the latest output line (this step routinely takes 5-20 minutes); on failure, the last 20 lines of stdout and stderr are included in the error. - Polls
http://<host>/about.jsonevery 5 seconds for up to 5 minutes. Deliberately plain HTTP, not HTTPS — a freshly-bootstrappedstandalone.ymlhas no SSL template enabled yet (that's a separate later step involving DNS and Let's Encrypt), so port 80 is the only thing that can answer. - Appends a
[[discourse]]entry todsc.toml:name,baseurl: https://<host>,ssh_host,ssh_user, andssh_port(omitted when 22, matching how existing entries work).apikey/api_usernameare left empty — create an API key on the new forum's admin panel and set them afterwards (dsc api-key create, then editdsc.tomlordsc setting... there is no direct "set my own api key" setting command; edit the file).
Flags¶
--host(required) — hostname or IP the box is reachable at over SSH, and the value written toDISCOURSE_HOSTNAME. Use the real public hostname if you have it; a bare IP works for a first bootstrap but you'll need to re-render before going live with a real domain.--email(required) — one or more admin/developer emails forDISCOURSE_DEVELOPER_EMAILS. Comma-separated for more than one.--smtp-host,--smtp-port,--smtp-user,--smtp-pass-stdin— SMTP configuration. Not just cosmetic: Discourse's normal signup flow sends a confirmation email before any account can log in — including the very first admin account. Without a working SMTP relay, nobody can actually get into the new site at all, even though every other step (including theabout.jsonpoll) succeeds fine regardless.dsc installprints a loud warning (twice — once up front, once in the final summary) if--smtp-hostis omitted, but doesn't refuse to proceed: there are legitimate reasons to defer (e.g. adding SMTP toapp.ymlby hand afterwards). A personal account (Gmail, Proton Mail, etc.) with an app-specific password is a fine temporary stopgap until a dedicated transactional provider is set up.--smtp-pass-stdinreads the password as one line from stdin (never as a bare argument, so it can't leak into shell history orps) and requires--smtp-host.--branch— Discourse git revision to build. Omit to usediscourse_docker's own default (tests-passed); usestablefor a slower-moving install.
Dry run¶
dsc install --dry-run … prints every SSH command, the fully-rendered app.yml's upload plan, the launcher invocation, and the about.json poll it would perform, and refuses every actual side effect — including the local dsc.toml write. No SSH connection or HTTP request happens at all under --dry-run.
Errors and re-running¶
Every step is written to be safely re-run: cloning is skipped if /var/discourse already exists (pulled instead), the app.yml write is a plain overwrite (not a diff — this is a from-zero bootstrap, not a declarative sync), and launcher bootstrap/start are themselves idempotent on the Discourse side. If dsc install fails partway through, fix the underlying problem and run the same command again.
Prerequisites¶
dsc install assumes a dsc harden-prepared box: a non-root sudo user with NOPASSWD sudo, and rootless Docker already installed and working for that user. Stage 3 of dsc harden (which will install Docker as part of hardening) is not yet shipped — see harden — so for now, install Docker yourself first:
- Rootless install, per the official guide:
curl -fsSL https://get.docker.com | sh,sudo apt install -y uidmap, then as the SSH user (not root):dockerd-rootless-setuptool.sh install. sudo setcap cap_net_bind_service=ep $(which rootlesskit)— without this, the rootless daemon cannot bind ports 80/443 and Discourse will never come up.loginctl enable-linger <user>— without this, the rootless daemon (and later, the Discourse container) dies the moment your SSH session ends.
dsc install itself only needs sudo for one thing: creating /var/discourse (since /var isn't user-writable) and handing ownership to the SSH user with chown. Everything after that — the git clone, the app.yml write, and launcher bootstrap/start — runs as that plain user with DOCKER_HOST pointed at the rootless socket, never as root. A rootful Docker target (where launcher needs sudo to reach /var/run/docker.sock) is not supported by Phase 1 — it would need a different, mutually-exclusive command sequence; tracked as a Phase 2 candidate in the spec.