A tool to install Python as SystemD or LaunchD service
Project description
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
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"
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
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file svci-1.1.0.tar.gz.
File metadata
- Download URL: svci-1.1.0.tar.gz
- Upload date:
- Size: 13.9 kB
- Tags: Source
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
008d1099f959fcd172727625796cc4f45bee6568a749a3bcc45e1f0f9b2d4e07
|
|
| MD5 |
58fbb89fef5a4b96d68989b4274d29d5
|
|
| BLAKE2b-256 |
69161fed8a9f84dde436f44bb40e79fcd7312f14ae44615768feddb8b1813ac8
|
File details
Details for the file svci-1.1.0-py3-none-any.whl.
File metadata
- Download URL: svci-1.1.0-py3-none-any.whl
- Upload date:
- Size: 17.1 kB
- Tags: Python 3
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
12209b171296ebcfb80bcd4a230184b66e3a897d7bfe48b4733bc4a442493790
|
|
| MD5 |
254718f4239ccc65e8d1e698da8ccb32
|
|
| BLAKE2b-256 |
1d3b5f92e527a079fd0712794c3ba6564e5c024721a62e480d07351c14a12a51
|