Files
Magent/docs/NATIVE_INSTALL.md
T

13 KiB

Native Linux installation (no Docker)

This is a manual, single-host production recipe for a Linux server with systemd. Neither Docker nor Portainer is required. For a terminal-only trial, Windows or macOS, use foreground installation. See the installation overview for platform limits and networking.

The operator manages OS updates, Python/Node, private keys, the reverse proxy and service lifecycle. The systemd files below are reviewable examples, not an automatic installer; adapt executable paths to your host and validate locally.

1. Prerequisites and layout

Install Python 3.14 with venv/pip, Node.js 24 with npm, Git, curl and a trusted TLS reverse proxy. Follow Python and Node.js instructions for your OS; distribution default packages may be older. Install both runtimes at service-accessible system paths outside /home and /root; a venv linked to a user-private pyenv/uv Python can be hidden by the units' ProtectHome setting. Do not replace the OS's own Python. Native wheels are architecture-dependent; if pip/npm need compilation, install the appropriate compiler/library prerequisites from the dependency maintainers rather than silently changing pinned versions. Do not use sudo pip install into system Python.

python3.14 --version
python3.14 -m venv --help
node --version
npm --version
command -v node

This recipe uses:

Path Purpose
/opt/magent Release source, Python venv, frontend dependencies/build
/etc/magent/backend.env Private backend keys and deployment configuration
/etc/magent/frontend.env Frontend address/bind settings; no backend secrets
/var/lib/magent/data Persistent SQLite, logs, branding, artwork and restore staging

Create a dedicated account and directories on a fresh host. If the account or paths already exist, inspect and reuse the intended installation; do not overwrite its configuration, clone into it or change ownership blindly.

sudo useradd --system --user-group --create-home --home-dir /var/lib/magent --shell /usr/sbin/nologin magent
sudo install -d -o magent -g magent -m 0755 /opt/magent
sudo install -d -o root -g root -m 0700 /etc/magent
sudo install -d -o magent -g magent -m 0700 /var/lib/magent/data
sudo -u magent git clone --branch release --single-branch https://git.amslabs.net/Rephl3x/Magent.git /opt/magent
sudo -u magent git -C /opt/magent rev-parse HEAD
sudo -u magent python3.14 -m venv /opt/magent/.venv
sudo -u magent /opt/magent/.venv/bin/python -m pip install -r /opt/magent/backend/requirements.txt

Record the checked-out commit. Use the release branch or a reviewed release commit, not the private development/deployment branches. The native API needs backend/requirements.txt, not Docker's Supervisor dependency file. Python virtual environments should be recreated at their final path rather than moved. See Python venv documentation.

2. Create private configuration once

Choose the final URL first, for example https://magent.example.com. DNS and TLS are configured separately in your reverse proxy. The native mode does not use container_bootstrap or generate keys automatically.

For a fresh installation only, run this standard-library script to create independent keys without printing them. It refuses to overwrite an existing file. The default URL below is an example and must be edited before starting services.

sudo python3.14 - <<'PY'
import base64
import os
from pathlib import Path
import secrets

path = Path('/etc/magent/backend.env')
values = {
    'JWT_SECRET': secrets.token_urlsafe(48),
    'SETTINGS_ENCRYPTION_KEY': base64.urlsafe_b64encode(secrets.token_bytes(32)).decode(),
    'SETUP_TOKEN': secrets.token_urlsafe(48),
    'MAGENT_MANAGED_SECRETS': 'false',
    'MAGENT_APPLICATION_URL': 'https://magent.example.com',
    'CORS_ALLOW_ORIGIN': 'https://magent.example.com',
    'AUTH_COOKIE_SECURE': 'true',
    'API_DOCS_ENABLED': 'false',
    'SQLITE_PATH': '/var/lib/magent/data/magent.db',
    'LOG_FILE': '/var/lib/magent/data/magent.log',
    'BRANDING_SOURCE': 'data',
}
fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
with os.fdopen(fd, 'w') as stream:
    stream.write(''.join(f'{name}={value}\n' for name, value in values.items()))
print('Created private backend configuration; edit the example URL before starting.')
PY
sudo install -o root -g root -m 0600 /opt/magent/deploy/native/magent-frontend.env.example /etc/magent/frontend.env
sudoedit /etc/magent/backend.env /etc/magent/frontend.env

The backend template shows the same fields with placeholders for reference; never run with those placeholders. Keep both files private and keep an encrypted off-host copy of backend keys. Run the install command above only for a new frontend environment file; during upgrades retain your existing file rather than copying the example again.

Set MAGENT_APPLICATION_URL in both files, and backend CORS_ALLOW_ORIGIN, to exactly the browser origin: scheme, hostname and any non-default port, without a path or trailing slash. For HTTPS set AUTH_COOKIE_SECURE=true; for a deliberate trusted-LAN HTTP installation set it false and use the explicit http:// URL in both files. The frontend uses this to avoid inappropriate CSP HTTPS upgrades. Do not use wildcard CORS or disable CSRF protections to fix an address mismatch.

Leave ADMIN_PASSWORD unset so the wizard creates the first administrator. Leave the internal MAGENT_RUNTIME_MANAGED flag unset. API docs remain disabled. All optional integration/environment controls are in ENVIRONMENT.md; configure app credentials through the wizard instead of copying every example variable into these files.

A .env file is not automatically loaded by the backend. The systemd unit loads backend.env explicitly. The frontend must never load that backend file or receive secrets in NEXT_PUBLIC_* variables.

3. Build the frontend

Run the build as the unprivileged service account. The backend address must be present at build time: otherwise this project defaults to Docker's http://backend:8000, which does not normally resolve on a native host.

sudo -u magent sh -c 'cd /opt/magent/frontend && npm ci --include=dev'
sudo -u magent sh -c 'cd /opt/magent/frontend && BACKEND_INTERNAL_URL=http://127.0.0.1:8000 NEXT_PUBLIC_API_BASE=/api NEXT_TELEMETRY_DISABLED=1 NODE_ENV=production npm run build'
sudo -u magent sh -c 'cd /opt/magent/frontend && cp -R public .next/standalone/ && cp -R .next/static .next/standalone/.next/'
sudo -u magent mkdir -p /opt/magent/frontend/.next/standalone/.next/cache

Keep the build tools/dev dependencies until the build is complete. Do not serve the source with next dev in production. This project uses Next's standalone output: run its server.js, with the public and .next/static directories copied as above. Changing the backend host/port requires rebuilding this bundle, not merely editing its runtime environment. See Next standalone deployment.

4. Install and validate the services

The supplied units run as magent, bind to loopback, use a read-only system view, private temporary directories and restricted writable paths. The backend has one worker. Its fixed working directory is important: artwork/branding use cwd/data, independently of SQLITE_PATH. Do not replace that directory with a symlink; portable backup rejects a symlinked asset root.

sudo install -o root -g root -m 0644 /opt/magent/deploy/native/magent-backend.service /etc/systemd/system/magent-backend.service
sudo install -o root -g root -m 0644 /opt/magent/deploy/native/magent-frontend.service /etc/systemd/system/magent-frontend.service
sudoedit /etc/systemd/system/magent-frontend.service
sudo systemd-analyze verify /etc/systemd/system/magent-backend.service /etc/systemd/system/magent-frontend.service
sudo systemctl daemon-reload
sudo systemctl enable --now magent-backend.service magent-frontend.service

Before verification, make frontend ExecStart match the system-wide Node 24 path reported by command -v node (/usr/bin/node in the template). Service managers do not inherit an interactive nvm shell; install Node at a service-accessible system path. Likewise adapt the source/venv paths if you changed this layout. Do not remove hardening settings just to mask an incorrect writable path.

Inspect systemd execution settings when adapting units to your distribution. After sets ordering, not application readiness: confirm the health checks below before exposing the site.

sudo systemctl status magent-backend.service magent-frontend.service --no-pager
curl --fail http://127.0.0.1:8000/health
curl --fail http://127.0.0.1:3000/api/health
curl --fail http://127.0.0.1:3000/api/setup/status
sudo journalctl -u magent-backend.service -u magent-frontend.service -n 100 --no-pager

Both health endpoints should report {"status":"ok"}. A fresh setup status has setup_required and needs_admin set to true. Check logs locally, but sanitize them before sharing. The frontend is not a standalone static site: both processes must stay running. It is normal to see a temporary API error if the backend is still starting.

5. Configure HTTPS and finish setup

Use the reverse-proxy instructions to send your chosen HTTPS hostname to 127.0.0.1:3000. Keep backend port 8000 private. For a remote browser without a proxy, use an SSH tunnel for a local trial or deliberately change the frontend bind address and matching URL for trusted-LAN use; the production units intentionally are not LAN listeners by default.

Retrieve only the setup token in your private administrative terminal:

sudo sed -n 's/^SETUP_TOKEN=//p' /etc/magent/backend.env

Open the final browser URL, create the administrator, configure apps and finish the wizard. Native installations use this manually persisted token, not the container command shown in the managed-install part of the help dialog. After administrator creation, remove SETUP_TOKEN using sudoedit and restart the backend. Do not remove/regenerate JWT_SECRET or SETTINGS_ENCRYPTION_KEY. Restarting never reopens first-admin signup on an existing database.

sudoedit /etc/magent/backend.env
sudo systemctl restart magent-backend.service

Routine operation, backup and restore

  • Start/stop/restart with systemctl; enablement starts services after boot. Check the journal and /var/lib/magent/data/magent.log for backend errors.
  • Use encrypted application backups. Portable exports do not include the environment files, deployment keys or TLS keys; back those up separately and protect their passphrases.
  • For an offline disaster-recovery snapshot, stop both Magent services and back up /var/lib/magent/data, /etc/magent and the exact source revision/unit configuration using your trusted backup tool, then start services again. Do not copy a live SQLite file and assume it is consistent.
  • A staged UI restore takes effect when you restart magent-backend.service. Keep one worker and no other writers, keep destination keys unchanged, then verify restored accounts and integrations. Native/manual restore may import the source's saved application URL: recheck Hosting & proxy against your destination environment and frontend URL after recovery.

Upgrade and roll back

Plan a maintenance window; this is not a rolling multi-worker deployment.

  1. Record git -C /opt/magent rev-parse HEAD, back up the application and private environment, and read migration/release notes. Keep the previous source and runtime dependency versions available.
  2. Stop both services. Fetch release as the source owner and review the exact intended commit; use git merge --ff-only origin/release only for a clean release checkout. Do not force-reset local changes.
  3. Install the new pinned backend requirements into the existing venv, or create a replacement venv at its final path if the Python version changed. Re-run all frontend dependency/build/static-copy steps above. Keep the same data directory and private environment; do not rerun initial key generation.
  4. Review any unit changes, validate and daemon-reload if needed, start services and check API health, setup/login, UI assets, integrations and backups.

For a rollback, stop both services, restore the recorded compatible source and dependency/build artifacts, and keep the original keys/data. If the upgrade changed the database incompatibly, use the matching pre-upgrade database backup with that older version; code-only rollback is not always safe. Portable restore should first use the same application version that created the backup.

To retire a native installation, disable/stop its two units first. Retain the data and private environment until an off-host restore has been verified. Do not delete /var/lib/magent as a troubleshooting step.