svci
A tool to install Python apps as systemd (Linux) or launchd (macOS) services.
Features
- Cross-platform: systemd on Linux, launchd on macOS
- Three service modes:
user,system, andsystem-at-user - ConfigArgParse-based CLI with CLI args, environment variables, and TOML config file support
--pyprojectflag to read config from[tool.svci]inpyproject.toml- Built-in templates with customizable overrides
- Dry-run by default,
--installto write to disk - DIY mode (
--diy) generates a deployment bundle with service file + README - Pre-flight checks:
.venvdetection, linger status (Linux), existing service detection - Colored unified diff before overwriting existing services
- D-Bus integration for systemd control (via jeepney)
- Modern launchctl commands (bootstrap/bootout/kickstart) for macOS
Requirements
- Python 3.10 or newer
- Linux (systemd) or macOS (launchd)
Installation
pip install svci
Or with uv:
uv tool install svci
Usage
Dry run (preview the generated service file)
svci \
--working-dir /path/to/app \
--run-cmd "uv run app --host 127.0.0.1 --port 7867"
Install a user service
svci \
--install \
--enable \
--start \
--working-dir /path/to/app \
--run-cmd "uv run app --host 127.0.0.1 --port 7867"
Install a system-wide service
sudo svci \
--install \
--service-mode system \
--name my-app \
--working-dir /srv/my-app \
--run-cmd "uv run app --host 127.0.0.1 --port 7867"
Install a system-wide name@user service
sudo svci \
--install \
--service-mode system-at-user \
--name my-app \
--user myuser \
--working-dir /srv/my-app \
--run-cmd "uv run app --host 127.0.0.1 --port 7867"
Show platform-specific management commands
svci --help-platform --name my-app --service-mode user
This prints all the commands you need to manage the service (enable, start, stop, restart, logs, remove), tailored to your platform (systemd or launchd) and service mode. Works standalone or after install/dry-run.
Generate a DIY deployment bundle
svci \
--diy \
--working-dir /path/to/app \
--run-cmd "uv run app --host 127.0.0.1 --port 7867"
This creates a ~/tmp/<name>/ directory with the service file and a README with manual deployment instructions.
Using pyproject.toml
Add a [tool.svci] section to your project's pyproject.toml:
[tool.svci]
name = "my-web-app"
description = "FastAPI app running via uv"
run_cmd = "uv run main.py --host 127.0.0.1 --port 8000"
service_mode = "user"
[tool.svci.environment]
DEBUG = "false"
PORT = "8000"
DATABASE_URL = "postgresql://localhost/mydb"
[tool.svci.systemd]
restart = "always"
restart_sec = 3
[tool.svci.launchd]
run_at_load = true
Then deploy with a single command from your project directory:
svci --pyproject --install --enable --start
Or point to a specific file:
svci --pyproject /path/to/pyproject.toml --install
When --pyproject is used, working_dir defaults to the directory containing the pyproject.toml. CLI arguments always override values from pyproject.toml.
[tool.svci] reference
| Key | Type | Description |
|---|---|---|
name |
string | Service name (default: directory name) |
description |
string | Service description |
run_cmd |
string | Command to execute |
working_dir |
string | Working directory (default: pyproject.toml directory) |
service_mode |
string | "user", "system", or "system-at-user" |
user |
string | User for system modes |
group |
string | Group for system modes (Linux only) |
template |
string | Path to custom template file |
| Section | Key | Type | Description |
|---|---|---|---|
[tool.svci.environment] |
any | string | Environment variables set in the service |
[tool.svci.systemd] |
restart |
string | Restart policy (default: "on-failure") |
[tool.svci.systemd] |
restart_sec |
integer | Seconds between restarts (default: 5) |
[tool.svci.launchd] |
run_at_load |
boolean | Start at login/boot (default: true) |
Configuration
svci looks for config files in:
~/.config/svci/config.toml
Custom templates can be placed at:
~/.config/svci/templates/systemd.service-template~/.config/svci/templates/launchd.plist-template
All CLI options can also be set via environment variables with the SVCI_ prefix (e.g., SVCI_WORKING_DIR, SVCI_RUN_CMD).
Priority order
CLI args > environment variables (SVCI_*) > --pyproject ([tool.svci]) > config file (~/.config/svci/config.toml) > defaults
Service modes
| Mode | Linux | macOS |
|---|---|---|
user |
systemd user unit (~/.config/systemd/user/) |
LaunchAgent (~/Library/LaunchAgents/) |
system |
systemd system unit (/etc/systemd/system/) |
LaunchDaemon (/Library/LaunchDaemons/) |
system-at-user |
name@.service template |
LaunchDaemon with UserName |
License
MIT
Metadata
Release files for svci 1.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| svci-1.2.0.tar.gz | 14.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| svci-1.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 31.9 kB
Release files / svci-1.2.0.tar.gz
| Download URL | svci-1.2.0.tar.gz |
|---|---|
| Size | 14.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9c5a2d0b28deb969b4fce911550e52d86e80f3c8c4fd72a2eed9b57afef2bb41
|
|
BLAKE2b-256 checksum How to use checksums |
e61d033eb0e20a6885153cd8879a67b21732f14e1c9ee3b319ce65075ef1b096
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / svci-1.2.0-py3-none-any.whl
| Download URL | svci-1.2.0-py3-none-any.whl |
|---|---|
| Size | 17.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
52cb72de00af2a23c3c276bf125526fe264a6898da0889efa1edf103b405e610
|
|
BLAKE2b-256 checksum How to use checksums |
4062576f279e1462b81df4f961eda8db66c70abb2b6283cfb14145d66fa4c1bc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.3 {"installer":{"name":"uv","version":"0.11.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|