-
Notifications
You must be signed in to change notification settings - Fork 1
Deployments
Procodile supports running multiple independent supervisors on the same machine.
For example, these two application roots can each run their own supervisor without interfering with each other:
/apps/foo/apps/bar
Each application root has its own Procfile, supervisor PID, control socket, logs, and managed processes.
Running multiple supervisors is a normal deployment model.
For example:
procodile -r /apps/foo start
procodile -r /apps/bar startThese are two separate supervisors, not one shared supervisor.
Different application roots work safely as long as you do not configure conflicting shared paths or ports.
Pay particular attention to:
pid_root-
log_pathandlog_root -
proxy_portandproxy_address allocate_port_from
If two applications are configured to use the same PID directory, log path, proxy listener, or port allocation range, they can still conflict even if their roots are different.
The global /etc/procodile file is only used to help the CLI determine which application root to operate on.
It does not create a shared supervisor. Each configured application still runs as its own independent supervisor.
A single-app configuration can look like this:
root: /apps/fooA multi-app configuration can look like this:
- name: Foo
root: /apps/foo
- name: Bar
root: /apps/barThis is equivalent to running commands with -r /apps/foo or -r /apps/bar manually.
A practical pattern is to create a dedicated Unix user for each application, for example deployer, and keep the application under that user's home directory:
/home/deployer/apps/myapp_production
This keeps process ownership, logs, sockets, PID files, and deploy-time permissions isolated per application.
If you are deploying a Ruby application and rely on tools such as RVM, it is usually a good idea to invoke Procodile through bash -lc "...". This helps ensure that shell startup files are loaded and that Ruby, Bundler, PATH, and related environment setup are initialized correctly before Procodile starts.
If you still want Procodile itself to remain the process manager, a reasonable compromise is to use systemd --user only to start the Procodile daemon at boot.
Example:
[Unit]
Description=procodile
StartLimitIntervalSec=0
[Service]
LimitCORE=infinity
LimitNOFILE=infinity
LimitNPROC=infinity
Type=oneshot
ExecStart=bash -lc '/usr/local/bin/procodile -r /home/deployer/apps/myapp_production start --clean'
ExecStop=bash -lc '/usr/local/bin/procodile -r /home/deployer/apps/myapp_production stop --stop-supervisor --wait'
RemainAfterExit=yes
[Install]
WantedBy=default.targetThis approach uses systemd only as a one-shot bootstrap mechanism to start Procodile and the application services it manages. Procodile still manages the application processes, restarts, logs, scheduling, and runtime issues.
Using -r /path/to/app is usually enough to avoid setting WorkingDirectory in the systemd unit. Procodile uses the application root to load configuration, and when it starts managed processes it also changes into that application root before executing them.
If you deploy through release directories and a current symlink, always point Procodile at the stable current path rather than a specific release directory. Otherwise, if Procodile is started from a concrete release path, later restarts may continue using that old release instead of the new current target.
For example:
procodile -r /home/deployer/apps/myapp/current start
# not
procodile -r /home/deployer/apps/myapp/releases/20260414-120001 startProcodile also exposes the resolved application root to managed processes through the APP_ROOT environment variable.
To allow a user service to start even when the user has not logged in, enable lingering for that user:
sudo loginctl enable-linger deployerThen install and enable the user unit as that user, for example:
systemctl --user daemon-reload
systemctl --user enable procodile.service
systemctl --user start procodile.serviceThis pattern works, but it has one important limitation: once procodile start exits successfully, systemd only knows that the start command completed. It does not directly supervise the long-running Procodile daemon after that.
That means:
- if the Procodile supervisor later dies unexpectedly, the user service may still appear active
-
Restart=on-failuredoes not behave like normal long-running service supervision here, because theExecStartcommand itself already exited successfully
So this pattern is best understood as:
- systemd starts Procodile at boot
- Procodile manages the application afterwards
After the user service has started the Procodile daemon, you still manage the application with normal procodile commands. A common pattern is to use one of these approaches:
-
define a shell alias that always runs Procodile with the correct
-rapplication root. For example:alias procodile_myapp="procodile -r /home/deployer/apps/myapp_production"
With this alias, you can run commands like:
procodile_myapp status
procodile_myapp reload
procodile_myapp restart- change into the application root and run
procodilethere directly. For example:
cd /home/deployer/apps/myapp_production
procodile statusIf you want systemd to supervise Procodile itself more strictly, run Procodile in the foreground under systemd instead:
ExecStart=bash -lc '/usr/local/bin/procodile start --foreground --clean'
Type=simpleThat gives systemd a real long-running main process to track, but it also means systemd is now supervising Procodile more directly.
If your goal is to avoid relying on systemd as the primary process manager, the user-service bootstrap pattern above is a reasonable compromise.
A simple deployment flow is:
- Deploy the new release.
- Run
procodile reloadif only configuration changed. - Run
procodile restartfor long-running process changes. - Use
procodile statusto confirm the new state.
For command details, see CLI Reference.