All guides
Containers · 6 min · Intermediate

Run systemd in an LXC Container

What an LXC container is, when you need one, and how services behave differently from a standard container.

A standard SparkCloud container has no init system. Its first process is sshd, so `systemctl` does nothing, and anything you start by hand is gone the next time the container stops. That is fine for a single app you launch from /app/start.sh, and a genuine wall for software that expects to be installed on a machine.

An LXC container is the answer to that: a full Linux system running the distribution's own systemd as PID 1. `systemctl enable --now nginx` behaves exactly as it does on a VM, and the service is back on its own after any restart, sleep, or wake from deep sleep.

When you actually want one

  • Software whose install instructions say `systemctl enable` — PostgreSQL, nginx, Redis, MariaDB, Docker-less service stacks.
  • Anything built around systemd itself: timers instead of cron, socket activation, journald, per-service resource limits.
  • A distro package that ships a unit file and expects it to be started for you.
  • Multi-service boxes where you would otherwise be reinventing an init system inside /app/start.sh.

If you are running one web app, a bot, or a worker, a standard container is smaller, starts faster, and snapshots far more cheaply. Reach for LXC when you need the init system, not by default.

Deploying one

  1. Containers → New Container. Pick LXC under Runtime.
  2. Choose Dynamic or Persistent exactly as you would otherwise — the runtime choice is independent of the billing type, and pricing is identical.
  3. Pick an image and disk size, then Deploy. First boot takes a little longer than a standard container because a real init system is coming up.
  4. SSH in with the host, port, and password on the container detail page.

Managing services

bash
apt update && apt install -y nginx
systemctl enable --now nginx
systemctl status nginx

# survives a restart, a sleep, and a wake from deep sleep:
reboot

Your app still needs to listen on port 80 to be reachable at your subdomain. /app/start.sh also still runs at every boot (as sparkcloud-app.service), so existing habits keep working — but a unit file is the better home for anything long-lived.

What is different

  • Snapshots cover the whole filesystem instead of just your changes, so deep sleep and waking from it take longer and use more of your storage quota. Sleeping and waking a dynamic LXC container is still a couple of seconds.
  • You get root inside the container, but that root is an unprivileged user on the host — nested Docker, loading kernel modules, and raw device access are all unavailable by design.
  • Outbound SMTP on port 25 is blocked, as it is for every container. Send mail through a provider on 587 or 465.