# Install Magent with Docker For a fresh installation, Docker Compose runs the published `rephl3xnz/magent:latest` image with persistent storage and the required runtime security settings. Magent contains both its Python API and Next.js frontend; you do not install Python, Node.js, a separate database, or your media apps as part of this procedure. No Dockerfile, source checkout, `.env`, manually generated keys, or default administrator password is needed. This guide covers Compose CLI, direct `docker run`, and building from source. For a graphical deployment, use [Portainer](PORTAINER.md). For installation without containers, see [native installation](NATIVE_INSTALL.md). Existing installations must keep their original data mount and keys; read [existing installations](#existing-installations) before changing a deployment. ## Prerequisites - A Docker daemon running **Linux containers**. Only `linux/amd64` has been validated for Magent. ARM64, Raspberry Pi and Apple Silicon are not advertised as supported targets; selecting amd64 emulation does not establish native ARM64 compatibility. - For Linux, install [Docker Engine for your distribution](https://docs.docker.com/engine/install/) and the [Docker Compose plugin](https://docs.docker.com/compose/install/linux/). Use the `docker compose` plugin commands shown here; the legacy `docker-compose` executable is outside this guide. Follow Docker's distribution-specific package instructions; installing only the CLI does not provide a running daemon. - On a supported Windows or macOS desktop, follow Docker's [Windows installation guide](https://docs.docker.com/desktop/setup/install/windows-install/) or [Mac installation guide](https://docs.docker.com/desktop/setup/install/mac-install/). Start Docker Desktop and use its Linux-container engine. Check Docker's host requirements and subscription terms. Docker Desktop is not supported on Windows Server. The container stops being available when its VM/daemon or host is shut down or asleep; plan that lifecycle before using a desktop as an always-on server. - A persistent Docker storage location with room for the image, database, artwork cache and backups. Follow [Docker Desktop backup and recovery](https://docs.docker.com/desktop/settings-and-maintenance/backup-and-restore/) before resetting or uninstalling it; its volumes live in the Linux VM. - A stable browser-facing address. Trusted-LAN HTTP can be used for initial local setup; arrange DNS and an HTTPS reverse proxy before public access. The host needs outbound access to the image registry and whichever optional integrations you configure. Check the selected daemon and Compose installation: ```sh docker version docker compose version docker info --format '{{.OSType}}/{{.Architecture}}' ``` The daemon must report Linux, with an x86-64/amd64 architecture for the validated image. On Linux, your account may need `sudo` for Docker commands. Access to the Docker socket or `docker` group grants powerful host privileges; follow [Docker's Linux post-installation guidance](https://docs.docker.com/engine/install/linux-postinstall/). The multi-line shell examples below use Bash, as available on Linux, macOS or an integrated WSL terminal. A separate PowerShell download example is included; the single-line Docker commands also work in PowerShell. Magent remains a Linux container in either case, not a native Windows-container or macOS application. ## Docker Compose ### 1. Save the deployment file Create a new directory for this installation and save the release branch's [raw compose.yml](https://git.amslabs.net/Rephl3x/Magent/raw/branch/release/compose.yml) there. Keep your customized copy for future operations instead of overwriting it when updating. You need only this file for the prebuilt image. Linux, macOS or WSL: ```sh mkdir magent-install cd magent-install curl --fail --location --output compose.yml https://git.amslabs.net/Rephl3x/Magent/raw/branch/release/compose.yml ``` PowerShell: ```powershell New-Item -ItemType Directory -Path magent-install Set-Location magent-install Invoke-WebRequest -Uri 'https://git.amslabs.net/Rephl3x/Magent/raw/branch/release/compose.yml' -OutFile compose.yml ``` Alternatively, open the raw link in your browser and save the plain text as `compose.yml`, not `compose.yml.txt`. It should contain a `services:` section with `image: rephl3xnz/magent:latest`, not an HTML page. If your network requires repository sign-in, download the raw file through your authenticated browser; do not insert account credentials into a shared shell command. All examples explicitly select `-f compose.yml` and project `-p magent`. Keep that project name stable: with the unchanged file, its volume is `magent_magent-data`. Changing the project name can create a different, empty volume; it does not move the database. If you choose another name, use it on every subsequent command. Docker documents [how project names select an installation](https://docs.docker.com/compose/how-tos/project-name/). ### 2. Review ports and start the container The supplied `3000:3000` mapping publishes port 3000 on host interfaces for LAN access. If that port is occupied, edit only the left side, for example `3100:3000`, and use port 3100 in your browser. For a reverse proxy running directly on the same host, use `127.0.0.1:3000:3000` to bind to loopback. Keep the data mount and security block intact. Validate the saved file, pull the image, and start it: ```sh docker compose -f compose.yml -p magent config --quiet docker compose -f compose.yml -p magent pull magent docker compose -f compose.yml -p magent up -d --no-build magent docker compose -f compose.yml -p magent ps ``` Wait until the container reports `healthy`; its first health check can take several seconds. A detached start completing does not by itself mean the application is ready. To inspect a startup problem: ```sh docker compose -f compose.yml -p magent logs --tail 100 magent ``` Review logs privately and redact sensitive information before sharing them. This deployment runs one Magent service and one SQLite database; do not scale it to multiple replicas sharing the same volume. ### 3. Retrieve the setup token Once the container is healthy, run this from your deployment directory: ```sh docker compose -f compose.yml -p magent exec --user magent magent python -m app.container_bootstrap setup-token ``` The command displays the private token that Magent generated at first start. It does not generate replacement keys, and it stops returning the token once an administrator exists. Keep its output private: someone with the token and access to an unclaimed installation can create its first administrator. The setup page's **Get setup token** button provides console instructions and copies the command. It does not expose the token through the public website. When automatic clipboard access is unavailable, select and copy the command manually. You do not need to open an interactive shell for the Compose command above; if using a container console, select `/bin/ash` and user `magent`. ### 4. Complete the browser wizard Open the Docker host's reachable address, for example `http://192.168.1.50:3000`, or your configured HTTPS hostname. On the same desktop as Docker, `http://localhost:3000` may be suitable for local-only use. Choose the address your users will actually open before creating the account. 1. Confirm the **Public Magent URL** shown on `/setup`. It must match the browser's origin: scheme, hostname and any non-default port, without a path, query, credentials or fragment. To use another hostname, open Magent there first. 2. Paste the setup token and create your administrator with a unique password of at least 12 characters. There is no shared default login. 3. Connect and test the media apps you use, then select preferences and finish. Optional integrations can be skipped. Background imports remain paused until setup is completed. 4. Export an encrypted backup from **Settings → Advanced tools → Backup & restore** and keep its passphrase separately. Managed installs save the confirmed origin and derive matching CORS and cookie security from it. Their database path is fixed at `/app/data/magent.db`, and API documentation stays disabled. Do not add manual signing/encryption keys or override these fixed managed settings to complete setup. Advanced legacy environment configuration is documented separately in [ENVIRONMENT.md](ENVIRONMENT.md). App connection addresses must be reachable from Magent's container. Inside a container, `localhost` refers to that container. Use a reachable LAN/DNS address or an intentionally shared Docker network for other services. Magent does not need a Docker socket mount or access to your media files. ## Docker CLI without Compose This is an alternative for a fresh installation managed without Compose. Record the complete command for future recreation. The example uses container `magent`, network `magent-run`, and a named volume `magent_magent-data`, matching the data-volume name used by the `-p magent` Compose example. Do not run both examples against that volume at once. The commands are not a migration between Compose and manually managed containers; existing deployments must retain their actual mounts and management method. ```sh docker volume create magent_magent-data docker network create magent-run docker pull rephl3xnz/magent:latest docker run --detach \ --name magent \ --network magent-run \ --publish 3000:3000 \ --mount type=volume,source=magent_magent-data,target=/app/data \ --restart unless-stopped \ --stop-timeout 30 \ --read-only \ --cap-drop ALL \ --security-opt no-new-privileges:true \ --init \ --tmpfs /tmp:rw,noexec,nosuid,size=64m,uid=1000,gid=1000 \ --tmpfs /app/frontend/.next/cache:rw,noexec,nosuid,size=128m,uid=1000,gid=1000 \ rephl3xnz/magent:latest ``` In PowerShell, use the same `docker run` arguments on one line, or replace each Bash continuation backslash with PowerShell's backtick continuation character. Do not paste the backslashes into PowerShell as separate commands. The data mount, published port, restart policy, 30-second stop grace period, read-only root, dropped capabilities, privilege restriction, init process and two temporary mounts match the supplied Compose settings. The image already selects the unprivileged `magent` user and includes its health check, so do not override the user or entrypoint. Runtime flags are documented in [Docker's run reference](https://docs.docker.com/reference/cli/docker/container/run/). Check readiness and retrieve the token: ```sh docker ps --filter name=magent docker inspect --format '{{.State.Health.Status}}' magent docker logs --tail 100 magent docker exec --user magent magent python -m app.container_bootstrap setup-token ``` Then follow the same [browser wizard](#4-complete-the-browser-wizard). For a different port or proxy topology, change `--publish` as described in [ports and HTTPS](#ports-https-and-browser-security). ## Build the container from source Use this path when you intentionally want to build the application yourself. It requires the full source tree and Docker build support; the prebuilt-image installation does not. Use a separate checkout directory: ```sh git clone --branch release --single-branch https://git.amslabs.net/Rephl3x/Magent.git Magent-source cd Magent-source docker compose -f compose.yml -f compose.build.yml -p magent config --quiet docker compose -f compose.yml -f compose.build.yml -p magent build magent docker compose -f compose.yml -f compose.build.yml -p magent up -d --no-build magent docker compose -f compose.yml -f compose.build.yml -p magent ps ``` For a reproducible build, check out the reviewed release commit before the build command. [compose.build.yml](../compose.build.yml) changes the image to `magent:local` and adds `build: .`; the storage and security settings still come from root `compose.yml`. It uses the same managed first-install workflow and needs no `.env`. Retrieve its token with: ```sh docker compose -f compose.yml -f compose.build.yml -p magent exec --user magent magent python -m app.container_bootstrap setup-token ``` Use **both** `-f` arguments on subsequent source-build operations, including restart, logs and upgrades. A command using only `compose.yml` would select the Docker Hub image instead. Keep the project name and volume stable. Builds for unvalidated architectures remain your own compatibility-testing responsibility. ## Ports, HTTPS and browser security Only frontend port 3000 needs publishing. The combined image routes `/api/*` internally; do not publish backend port 8000 or configure a second browser API origin. Keep the whole application at the root of its hostname, including `/api` and `/_next` paths. For public access, configure DNS, a valid TLS certificate and an HTTPS reverse proxy. TLS terminates at that proxy; Magent does not provision it. A proxy running directly on the Docker host can forward to `127.0.0.1:3000` when Magent is published on host loopback. A containerized proxy needs an explicitly shared Docker network or reachable host interface: its own loopback is not the host. See the [reverse-proxy examples](PUBLIC_RELEASE.md#https-public-urls-and-reverse-proxies). The default LAN port mapping listens on host interfaces. Do not internet-forward the plain-HTTP port. Confirm your firewall actually filters Docker-published ports; Linux Docker forwarding can bypass ordinary `ufw` rules. Follow [Docker's firewall documentation](https://docs.docker.com/engine/network/packet-filtering-firewalls/) for the daemon and network in use. Confirm the public HTTPS origin during setup, or change it deliberately in administrator settings when moving addresses. Cookies and request-origin checks must agree with the address open in the browser. After deliberately changing the saved origin, restart Magent so its frontend also reloads the origin-dependent security policy. For the Compose installation, use `docker compose -f compose.yml -p magent restart magent`; for source builds, include `-f compose.build.yml` as well. HTTPS also enables browser features requiring a secure context. Do not resolve login failures by disabling origin checks, using wildcard CORS, or weakening cookie protection. Do not cache setup, login, authenticated pages or API responses at the proxy/CDN. Preserve Magent's Content Security Policy and per-response script nonces; mixing cached HTML with another response's CSP can leave the page unable to run. Allow at least 34 MiB for the full backup-restore HTTP upload. ## Persistence and backups With `-p magent`, root Compose creates `magent_magent-data` and mounts it at `/app/data`. It contains the database, settings, cached artwork, branding and private `bootstrap-secrets.json`. That file holds the generated deployment keys. Keep it together with the raw database; deleting it does not reset a password and can make encrypted settings unrecoverable. Docker host administrators can access the volume, so protect the host and its backups. Use the application's encrypted `.magent-backup` export for portable recovery, and test restoring it to a disposable instance of the same version. The export excludes deployment keys and re-encrypts settings for the destination's keys when restored. Managed restore retains the destination's confirmed URL. See [backup and restore](installation-and-recovery.md) for limits and the complete procedure; the backup passphrase cannot be recovered. For an offline snapshot or copy, stop only Magent, back up the entire volume consistently, and start it again after the copy completes: ```sh docker compose -f compose.yml -p magent stop magent # Take and verify a protected snapshot/copy of the complete magent_magent-data volume. docker compose -f compose.yml -p magent start magent ``` Keep SQLite sidecar files and original generated keys with that full-volume copy. Copying only the live database file is not an equivalent backup. Preserve your deployment file, chosen image digest, proxy configuration and backup passphrase separately. For direct Docker use, the corresponding commands are `docker stop --timeout 30 magent` and `docker start magent`. ## Pin an image, update, or roll back `latest` is a moving tag. Before an update, export a backup, retain the deployment definition and record the image actually running: ```sh docker compose -f compose.yml -p magent images magent ``` Use the reported image ID in the next command, replacing `IMAGE_ID`: ```sh docker image inspect IMAGE_ID --format '{{json .RepoDigests}}' ``` Record the complete `rephl3xnz/magent@sha256:...` reference, together with the image ID. A locally built image may not have a repository digest; keep its source commit and a retained image tag/archive. To pin a published image, edit only `image:` in your saved Compose file to the recorded full digest reference or a published release tag. A digest is immutable; an ordinary tag can move. See [Docker's digest-pull documentation](https://docs.docker.com/reference/cli/docker/image/pull/). After reviewing the target release's compatibility notes and selecting the image in your saved file, update only Magent: ```sh docker compose -f compose.yml -p magent config --quiet docker compose -f compose.yml -p magent pull magent docker compose -f compose.yml -p magent up -d --no-deps --no-build magent docker compose -f compose.yml -p magent ps docker compose -f compose.yml -p magent logs --tail 100 magent ``` An updated image causes Compose to recreate the service while retaining its mounted volume. A plain restart does not pull or apply a newer image. Verify health, sign-in, settings, enabled integrations and invites after the update. Docker documents [recreation and volume preservation](https://docs.docker.com/reference/cli/docker/compose/up/). For a direct `docker run` installation, first record its image ID and repository digest, save the full run command and back up the volume. Pull the selected replacement, stop and remove only the `magent` container, then repeat the saved run command with that image and the **same named volume**. Do not remove the volume or drop security flags during recreation. For source builds, back up, select the reviewed source revision, and repeat the build/up commands with both Compose files instead of pulling the Hub image. For rollback, select the previously recorded image and recreate only Magent. An older image may be unable to read data migrated by a newer version; restore the matching pre-update backup if the release requires it. Restoring that backup discards changes made since it was taken. Keep the current data backed up before attempting recovery. Never add `--volumes` or `-v` to a Compose `down` command during an update or routine recovery: it removes declared named volumes. An ordinary `down` also stops/removes the service and its network and is unnecessary for normal updates. Avoid volume pruning and Docker Desktop data resets unless you intend to erase their contents. See [Docker's down reference](https://docs.docker.com/reference/cli/docker/compose/down/). ## Troubleshooting | Symptom | Check | | --- | --- | | `docker compose` is unavailable | Install the Compose plugin and confirm `docker compose version`. Start the selected Docker daemon/Desktop instance. | | Cannot connect to the daemon or permission denied | Check `docker version`, the selected Docker context, and the deployment account's access. Do not expose an unauthenticated Docker API. | | No matching image manifest or an executable-format error | Check Linux-container mode and CPU architecture. Only Linux/amd64 is validated; do not assume ARM64 support. | | Port 3000 is already allocated | Identify the existing listener. Choose another host port such as `3100:3000` in your saved file and use that address in setup. | | Browser cannot reach Magent | Check `ps`, health and logs, the Docker host's reachable IP, published port, and Docker-aware firewall rules. A loopback bind is reachable only from its host. | | Fresh setup appears after an update | Stop and check the original project name and data mount. Do not create another administrator or replace generated keys to work around an empty/wrong volume. | | Token command says the database is uninitialized | Wait for healthy status, then inspect startup logs if it remains unhealthy. Do not generate a second secrets file. | | Token command says initial setup is no longer available | An administrator exists or setup is complete. Sign in with the established account; recreating the container does not reopen bootstrap. | | Login rejects the origin or returns to sign-in | Use the exact saved origin, including scheme and port. Check HTTPS/proxy configuration and cookie handling. A domain, LAN IP and `localhost` are different origins. | | Page stays blank or scripts are blocked by CSP | Inspect browser console/network errors. Remove unintended proxy/CDN HTML caching and conflicting security headers; preserve the application's CSP and nonces. Hard-refresh after correcting the proxy. | | Copy command is unavailable over LAN HTTP | Use the selected command's manual-copy fallback, or configure HTTPS. Other secure-context browser features may also need HTTPS. | | A service connection to `localhost` fails | Use an address reachable from the container, or an explicitly shared network with that service. | | Read-only/permission errors | Keep both tmpfs mounts and the correct data volume. The image runs as UID/GID 1000:1000. For an existing bind mount, back up and correct only that verified application directory; do not run Magent privileged or as root. | | A backup upload fails at the proxy | Allow at least 34 MiB for the multipart upload and consult the application backup limits. Do not post backups or passphrases in support logs. | ## Existing installations The root template is for fresh managed installations. It does not migrate a manual-secret deployment, change an existing bind mount into a named volume, or replace established keys. Retain the original project, volume or bind mount, database location, signing/encryption keys and environment settings. An empty volume is a new installation, not evidence that old data was migrated. Continue using your saved deployment definition or the advanced [manual-secret guide](PUBLIC_RELEASE.md#advancedmanual-secrets) and [docker-compose.hub.yml](../docker-compose.hub.yml) where appropriate. Review the [upgrade and recovery guidance](PUBLIC_RELEASE.md#existing-installations-and-upgrades) before changing storage or secret management. Never run two Magent instances against the same SQLite volume.