Skip to content

Self-hosting with Podman

The office install is HTTPS on port 47391 at https://app.getautomagicsocial.com:47391. You can run the same shape on your own server. Postgres is not opened on the host. The site asks for a sign-in. There is no guest view of customers, posts, or connected accounts.

Nothing in this guide connects a live social account for you. You run the commands on the server.

One image runs four commands: migrate (applies database changes, then exits), api (the website, the API, and the MCP address, on port 8787 inside the private network), worker (sends approved posts when a network is configured), and bootstrap (creates the first owner, once, then exits).

Caddy is a separate small container. It is the only program that listens on the public port. It presents the certificate and passes traffic to the API.

Name What it is
Port 47391 The only new port
Network automagic Private network for these containers
Volume automagic-pg The database files
Volume automagic-media Uploaded pictures and video
Volume automagic-caddy The certificate authority. Keep it. If you delete it, every computer must trust a new certificate.

deploy/up.sh starts this stack. deploy/quadlet/install.sh installs systemd units so it comes back after a reboot. deploy/podman-compose.yml describes the same containers if you already use compose. Use one of those, not two at the same time.

  • A normal user on the server, not root. Podman runs as that user.
  • loginctl enable-linger for that user, so the site stays up after they log out.
  • openssl, to create passwords.
  • Port 47391 free. Do not take 80, 443, 3000, 5432, or 8080 if something else already uses them.

From the repository directory, render the env files. They are readable only by this user. Do not commit them.

Terminal window
chmod +x deploy/*.sh deploy/quadlet/install.sh
deploy/render-env.sh

Then set AUTOMAGIC_LAN_IP to the server’s address on the local network, such as 192.168.1.20. That example is not your server. Leave BOOTSTRAP_PASSWORD empty so the first start writes a long random password to deploy/.owner-credentials and does not print it. Set BOOTSTRAP_EMAIL only if you want an address other than owner@getautomagicsocial.com.

Leave the YouTube, TikTok, X, Instagram, LinkedIn, and blog secrets empty until those apps exist. Leave X_HTTP_ALLOW_NETWORK unset until you mean to call X. Leave TIKTOK_APP_AUDITED unset. Leave MEDIA_PUBLIC_ORIGIN unset until a public https origin can serve media.

deploy/preflight.sh stops if 47391 is taken, or if a container, volume, or network with these names belongs to something else. It does not stop other apps.

Open only 47391/tcp on the firewall. Do not open 5432. On the router, forward TCP 47391 to the server’s LAN address, same port. If you use the name app.getautomagicsocial.com, leave that DNS record pointed at the server and do not proxy it in a way that hides the certificate this server presents.

Terminal window
podman build --format docker -f Containerfile -t localhost/automagic-social:latest .
deploy/up.sh

--format docker keeps the image health check. The image runs as a user named automagic, not as root. It reads settings from the environment only. Secrets are not baked into the image. Docker works for the same Containerfile. Set CONTAINER_RUNTIME=docker when you run the scripts.

Do not push the image to a public registry. If you build on another machine, podman save and podman load carry the file across.

After you change the code, rebuild and run deploy/up.sh update. The database container keeps running. deploy/up.sh reset-owner replaces the owner password, writes it to deploy/.owner-credentials, and signs that person out everywhere. The password is not shown on screen.

Caddy’s certificate is issued by its own local authority (tls internal). It is not a public certificate. Browsers warn until each computer trusts that authority. The warning is expected. Do not type the password on a warning page.

The authority covers the public name, the LAN name automagic.lan, and the address in AUTOMAGIC_LAN_IP. Copy the CA out of the Caddy container and trust it on each computer:

Terminal window
podman cp automagic-caddy:/data/caddy/pki/authorities/local/root.crt "$HOME/automagic-root.crt"
  • Fedora or RHEL: copy it into /etc/pki/ca-trust/source/anchors/ and run update-ca-trust.
  • Ubuntu: copy it into /usr/local/share/ca-certificates/ and run update-ca-certificates.
  • macOS: add it to the System keychain as a trusted root.
  • Windows: certutil -addstore -f "ROOT" automagic-root.crt from an administrator prompt.
  • Firefox keeps its own list unless you import the file or set security.enterprise_roots.enabled to true.

Check from the server, with the CA file:

Terminal window
curl --cacert "$HOME/automagic-root.crt" \
--resolve app.getautomagicsocial.com:47391:127.0.0.1 \
https://app.getautomagicsocial.com:47391/api/health

A good answer is {"ok":true}. deploy/check.sh also checks that Postgres and the API have no host port, and that a visitor who is not signed in is refused by /api/auth/me.

Terminal window
loginctl enable-linger "$USER"
deploy/quadlet/install.sh --start

The units live in ~/.config/containers/systemd/. Postgres still has no host port.

Register the public name, including the port, as the redirect URI. A private LAN address is not a redirect the product will send, and the networks will not accept it. Trust the CA on the computer that clicks Connect before you start. If the browser is still showing a certificate warning, the redirect will not finish.

Some providers reject a certificate that is not from a public authority, or they refuse a port other than 443. Use a temporary tunnel for that connection, then go back to the office address. While a tunnel mode is on, other computers on the office network cannot open the site, because it listens only on the server itself.

Keep COOKIE_SECURE on behind HTTPS. Set the public origins to the public addresses. Keep the encryption key and the network secrets on the server. Changing the encryption key makes stored tokens unreadable.