{"id":13602480,"url":"https://github.com/vifreefly/procsd","last_synced_at":"2025-04-05T21:09:29.579Z","repository":{"id":37561659,"uuid":"156067485","full_name":"vifreefly/procsd","owner":"vifreefly","description":"Manage your application processes in production hassle-free like Heroku CLI with Procfile and Systemd","archived":false,"fork":false,"pushed_at":"2021-02-22T21:27:11.000Z","size":116,"stargazers_count":189,"open_issues_count":2,"forks_count":5,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-29T20:07:21.038Z","etag":null,"topics":["automation","capistrano","cli","deployment","digitalocean","foreman","heroku-cli","linux","ngnix","procfile","production","systemd","vps"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vifreefly.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-11-04T09:38:28.000Z","updated_at":"2024-08-21T16:15:56.000Z","dependencies_parsed_at":"2022-08-20T23:40:35.576Z","dependency_job_id":null,"html_url":"https://github.com/vifreefly/procsd","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vifreefly%2Fprocsd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vifreefly%2Fprocsd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vifreefly%2Fprocsd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vifreefly%2Fprocsd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vifreefly","download_url":"https://codeload.github.com/vifreefly/procsd/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247399878,"owners_count":20932880,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automation","capistrano","cli","deployment","digitalocean","foreman","heroku-cli","linux","ngnix","procfile","production","systemd","vps"],"created_at":"2024-08-01T18:01:24.790Z","updated_at":"2025-04-05T21:09:29.563Z","avatar_url":"https://github.com/vifreefly.png","language":"Ruby","readme":"# Procsd\n\nI do like the way how simple is managing of application processes in production on Heroku with [Procfile](https://devcenter.heroku.com/articles/procfile). How easily can be accessed application logs with [heroku logs](https://devcenter.heroku.com/articles/logging) command. Just type `heroku create` and you're good to go.\n\nCan we have something similar on the cheap Ubuntu VPS from DigitalOcean? Yes we can, all we need is a **systemd wrapper** which allows to export application processes from Procfile to system services, and control them/check status/access logs using simple commands.\n\n\u003e These days most of Linux distributions (including Ubuntu) has systemd as a default system processes manager. That's why it is a good idea to use systemd for managing application processes in production (for simple cases).\n\n## Getting started\n\n\u003e **Note:** latest version of Procsd is `0.5.3`. Since version `0.4.0` there are some breaking changes. Check the [CHANGELOG.md](CHANGELOG.md). To update to the latest version, run `$ gem update procsd` or `$ bundle update procsd` (if you have already installed procsd).\n\n\u003e **Note:** Procsd works best with Capistrano integration: [vifreefly/capistrano-procsd](https://github.com/vifreefly/capistrano-procsd)\n\nInstall `procsd` first: `$ gem install procsd`. Required Ruby version is `\u003e= 2.3.0`.\n\nLet's say you have following application's Procfile:\n\n```yaml\nweb: bundle exec rails server -p $PORT\nworker: bundle exec sidekiq -e $RAILS_ENV\n```\nand you want to have one instance of web process \u0026\u0026 two instances of worker process. Create inside application directory `procsd.yml` config file:\n\n```yaml\napp: sample_app\nformation: web=1,worker=2\nenvironment:\n  PORT: 2501\n  RAILS_ENV: production\n  RAILS_LOG_TO_STDOUT: true\n```\n\n\u003e The only required option in `procsd.yml` is `app` (application name). Also you can provide custom Systemd directory path (`systemd_dir` option, default is _/etc/systemd/system_)\n\nConfiguration is done.\n\n### Create an application (export to Systemd)\n\u003e To disable and remove application from Systemd there is command `$ procsd destroy`.\n\n```\ndeploy@server:~/sample_app$ procsd create\n\nValue of the --user option: deploy\nValue of the --dir option: /home/deploy/sample_app\nValue of the --path option: /home/deploy/.rbenv/shims:/home/deploy/.rbenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin\n\nCreating app units files in the systemd directory (/etc/systemd/system)...\nCreate: /etc/systemd/system/sample_app-web.1.service\nCreate: /etc/systemd/system/sample_app-worker.1.service\nCreate: /etc/systemd/system/sample_app-worker.2.service\nCreate: /etc/systemd/system/sample_app.target\nReloaded configuraion (daemon-reload)\nCreated symlink /etc/systemd/system/multi-user.target.wants/sample_app.target → /etc/systemd/system/sample_app.target.\nEnabled app target sample_app.target\nApp services were created and enabled. Run `start` to start them\n\nNote: add following line to the sudoers file (`$ sudo visudo`) if you don't want to type password each time for start/stop/restart commands:\ndeploy ALL=NOPASSWD: /bin/systemctl start sample_app.target, /bin/systemctl stop sample_app.target, /bin/systemctl restart sample_app.target\n```\n\nYou can provide additional options for `create` command:\n* `--user` - name of the user, default is current _$USER_ env variable\n* `--dir` - application's working directory, default is current _$PWD_ env variable\n* `--path` - $PATH to include to the each service. Default is current _$PATH_ env variable\n* `--add-to-sudoers` - if option present, procsd will create sudoers rule file `/etc/sudoers.d/app_name` which allow to start/stop/restart app services without a password prompt (passwordless sudo).\n* `--or-restart` - if option provided and services already created, procsd will skip creation and call instead `restart` command. Otherwise (if services are not present), they will be created and (in additional) started. It's useful option for deployment tools like Capistrano, Mina, etc.\n\n\n### Start application\n\u003e Other control commands: `stop` and `restart`\n\n\u003e You can start/stop/restart a particular process by providing it's name, i.e.: `$ procsd restart worker`\n\n```\ndeploy@server:~/sample_app$ procsd start\n\nStarted app services (sample_app.target)\n```\n\n### Check the status\n\u003e You can filter processes, like `$ procsd status worker` (show status only for worker processes) or `$ procsd status worker.2` (show status only for worker.2 process)\n\n\u003e To show status of the main application target: `$ procsd status --target`\n\n```\ndeploy@server:~/sample_app$ procsd status\n\n● sample_app-web.1.service\n   Loaded: loaded (/etc/systemd/system/sample_app-web.1.service; static; vendor preset: enabled)\n   Active: active (running) since Sun 2018-11-04 01:54:15 +04; 1min 51s ago\n Main PID: 8828 (ruby)\n    Tasks: 13 (limit: 4915)\n   Memory: 83.6M\n   CGroup: /system.slice/sample_app-web.1.service\n           └─8828 puma 3.12.0 (tcp://0.0.0.0:2500) [sample_app]\n\n2018-11-04T01:54:15+0400 systemd[1]: Started sample_app-web.1.service.\n2018-11-04T01:54:17+0400 sample_app-web.1[8828]: =\u003e Booting Puma\n2018-11-04T01:54:17+0400 sample_app-web.1[8828]: =\u003e Rails 5.2.1 application starting in production\n2018-11-04T01:54:17+0400 sample_app-web.1[8828]: =\u003e Run `rails server -h` for more startup options\n2018-11-04T01:54:17+0400 sample_app-web.1[8828]: Puma starting in single mode...\n2018-11-04T01:54:17+0400 sample_app-web.1[8828]: * Version 3.12.0 (ruby 2.3.0-p0), codename: Llamas in Pajamas\n2018-11-04T01:54:17+0400 sample_app-web.1[8828]: * Min threads: 5, max threads: 5\n2018-11-04T01:54:17+0400 sample_app-web.1[8828]: * Environment: production\n2018-11-04T01:54:17+0400 sample_app-web.1[8828]: * Listening on tcp://0.0.0.0:2500\n2018-11-04T01:54:17+0400 sample_app-web.1[8828]: Use Ctrl-C to stop\n\n● sample_app-worker.1.service\n   Loaded: loaded (/etc/systemd/system/sample_app-worker.1.service; static; vendor preset: enabled)\n   Active: active (running) since Sun 2018-11-04 01:54:15 +04; 1min 51s ago\n Main PID: 8826 (bundle)\n    Tasks: 15 (limit: 4915)\n   Memory: 87.8M\n   CGroup: /system.slice/sample_app-worker.1.service\n           └─8826 sidekiq 5.2.2 sample_app [0 of 10 busy]\n\n2018-11-04T01:54:15+0400 systemd[1]: Started sample_app-worker.1.service.\n2018-11-04T01:54:17+0400 sample_app-worker.1[8826]: 2018-11-03T21:54:17.655Z 8826 TID-grcvqfyom INFO: Running in ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]\n2018-11-04T01:54:17+0400 sample_app-worker.1[8826]: 2018-11-03T21:54:17.655Z 8826 TID-grcvqfyom INFO: See LICENSE and the LGPL-3.0 for licensing details.\n2018-11-04T01:54:17+0400 sample_app-worker.1[8826]: 2018-11-03T21:54:17.655Z 8826 TID-grcvqfyom INFO: Upgrade to Sidekiq Pro for more features and support: http://sidekiq.org\n2018-11-04T01:54:17+0400 sample_app-worker.1[8826]: 2018-11-03T21:54:17.655Z 8826 TID-grcvqfyom INFO: Booting Sidekiq 5.2.2 with redis options {:id=\u003e\"Sidekiq-serv…, :url=\u003enil}\n2018-11-04T01:54:17+0400 sample_app-worker.1[8826]: 2018-11-03T21:54:17.658Z 8826 TID-grcvqfyom INFO: Starting processing, hit Ctrl-C to stop\n\n● sample_app-worker.2.service\n   Loaded: loaded (/etc/systemd/system/sample_app-worker.2.service; static; vendor preset: enabled)\n   Active: active (running) since Sun 2018-11-04 01:54:15 +04; 1min 51s ago\n Main PID: 8827 (bundle)\n    Tasks: 15 (limit: 4915)\n   Memory: 87.8M\n   CGroup: /system.slice/sample_app-worker.2.service\n           └─8827 sidekiq 5.2.2 sample_app [0 of 10 busy]\n\n2018-11-04T01:54:15+0400 systemd[1]: Started sample_app-worker.2.service.\n2018-11-04T01:54:17+0400 sample_app-worker.2[8827]: 2018-11-03T21:54:17.713Z 8827 TID-gniahzm1r INFO: Running in ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]\n2018-11-04T01:54:17+0400 sample_app-worker.2[8827]: 2018-11-03T21:54:17.713Z 8827 TID-gniahzm1r INFO: See LICENSE and the LGPL-3.0 for licensing details.\n2018-11-04T01:54:17+0400 sample_app-worker.2[8827]: 2018-11-03T21:54:17.714Z 8827 TID-gniahzm1r INFO: Upgrade to Sidekiq Pro for more features and support: http://sidekiq.org\n2018-11-04T01:54:17+0400 sample_app-worker.2[8827]: 2018-11-03T21:54:17.714Z 8827 TID-gniahzm1r INFO: Booting Sidekiq 5.2.2 with redis options {:id=\u003e\"Sidekiq-serv…, :url=\u003enil}\n2018-11-04T01:54:17+0400 sample_app-worker.2[8827]: 2018-11-03T21:54:17.716Z 8827 TID-gniahzm1r INFO: Starting processing, hit Ctrl-C to stop\n```\n\nAlso you can see status in short format:\n\n```\ndeploy@server:~/sample_app$ procsd status --short\n\nsample_app-web.1.service    loaded active running sample_app-web.1.service\nsample_app-worker.1.service loaded active running sample_app-worker.1.service\nsample_app-worker.2.service loaded active running sample_app-worker.2.service\n```\n\n\n### Check the logs\n\u003e Like with command `status`, you can filter logs by passing the name of process as an argument: `$ procsd logs web` (show logs only for web processes, if any)\n\n```\ndeploy@server:~/sample_app$ procsd logs\n\n-- Logs begin at Sun 2018-10-21 00:38:42 +04, end at Sun 2018-11-04 01:54:17 +04. --\n2018-11-04T01:54:15+0400 systemd[1]: Started sample_app-worker.1.service.\n2018-11-04T01:54:15+0400 systemd[1]: Started sample_app-worker.2.service.\n2018-11-04T01:54:15+0400 systemd[1]: Started sample_app-web.1.service.\n2018-11-04T01:54:17+0400 sample_app-worker.1[8826]: 2018-11-03T21:54:17.655Z 8826 TID-grcvqfyom INFO: Running in ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]\n2018-11-04T01:54:17+0400 sample_app-worker.1[8826]: 2018-11-03T21:54:17.655Z 8826 TID-grcvqfyom INFO: See LICENSE and the LGPL-3.0 for licensing details.\n2018-11-04T01:54:17+0400 sample_app-worker.1[8826]: 2018-11-03T21:54:17.655Z 8826 TID-grcvqfyom INFO: Upgrade to Sidekiq Pro for more features and support: http://sidekiq.org\n2018-11-04T01:54:17+0400 sample_app-worker.1[8826]: 2018-11-03T21:54:17.655Z 8826 TID-grcvqfyom INFO: Booting Sidekiq 5.2.2 with redis options {:id=\u003e\"Sidekiq-server-PID-8826\", :url=\u003enil}\n2018-11-04T01:54:17+0400 sample_app-worker.1[8826]: 2018-11-03T21:54:17.658Z 8826 TID-grcvqfyom INFO: Starting processing, hit Ctrl-C to stop\n2018-11-04T01:54:17+0400 sample_app-worker.2[8827]: 2018-11-03T21:54:17.713Z 8827 TID-gniahzm1r INFO: Running in ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]\n2018-11-04T01:54:17+0400 sample_app-worker.2[8827]: 2018-11-03T21:54:17.713Z 8827 TID-gniahzm1r INFO: See LICENSE and the LGPL-3.0 for licensing details.\n2018-11-04T01:54:17+0400 sample_app-worker.2[8827]: 2018-11-03T21:54:17.714Z 8827 TID-gniahzm1r INFO: Upgrade to Sidekiq Pro for more features and support: http://sidekiq.org\n2018-11-04T01:54:17+0400 sample_app-worker.2[8827]: 2018-11-03T21:54:17.714Z 8827 TID-gniahzm1r INFO: Booting Sidekiq 5.2.2 with redis options {:id=\u003e\"Sidekiq-server-PID-8827\", :url=\u003enil}\n2018-11-04T01:54:17+0400 sample_app-worker.2[8827]: 2018-11-03T21:54:17.716Z 8827 TID-gniahzm1r INFO: Starting processing, hit Ctrl-C to stop\n2018-11-04T01:54:17+0400 sample_app-web.1[8828]: =\u003e Booting Puma\n2018-11-04T01:54:17+0400 sample_app-web.1[8828]: =\u003e Rails 5.2.1 application starting in production\n2018-11-04T01:54:17+0400 sample_app-web.1[8828]: =\u003e Run `rails server -h` for more startup options\n2018-11-04T01:54:17+0400 sample_app-web.1[8828]: Puma starting in single mode...\n2018-11-04T01:54:17+0400 sample_app-web.1[8828]: * Version 3.12.0 (ruby 2.3.0-p0), codename: Llamas in Pajamas\n2018-11-04T01:54:17+0400 sample_app-web.1[8828]: * Min threads: 5, max threads: 5\n2018-11-04T01:54:17+0400 sample_app-web.1[8828]: * Environment: production\n2018-11-04T01:54:17+0400 sample_app-web.1[8828]: * Listening on tcp://0.0.0.0:2500\n2018-11-04T01:54:17+0400 sample_app-web.1[8828]: Use Ctrl-C to stop\n```\n\nSystemd provides [a lot of possibilities](https://www.digitalocean.com/community/tutorials/how-to-use-journalctl-to-view-and-manipulate-systemd-logs) to display and manage application logs (`journalctl` command). Procsd supports following options:\n* `-n` - Specify how many last lines to print. Default is 100\n* `-t` - Tail, display recent logs and leave the session open for real-time logs to stream in\n* `--system` - Show only systemd messages about services (start/stop/restart/fail etc.)\n* `--priority` - Filter messages by a [particular log level.](https://www.digitalocean.com/community/tutorials/how-to-use-journalctl-to-view-and-manipulate-systemd-logs#by-priority) For example show only error messages: `procsd logs --priority err`\n* `--grep` - [Filter output](https://www.freedesktop.org/software/systemd/man/journalctl.html#-g) to messages where message matches the provided query (may not work for [some](https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/1751006) Linux distributions)\n\n### Execute processes defined in Procfile\n\nCurrently, procsd can not run all processes in development like `foreman start` does. But you can run one single process using `procsd exec` command:\n\n```\ndeploy@server:~/sample_app$ procsd exec web\n\n=\u003e Booting Puma\n=\u003e Rails 5.2.1 application starting in production\n=\u003e Run `rails server -h` for more startup options\nPuma starting in single mode...\n* Version 3.12.0 (ruby 2.3.0-p0), codename: Llamas in Pajamas\n* Min threads: 5, max threads: 5\n* Environment: production\n* Listening on tcp://localhost:2501\nUse Ctrl-C to stop\n```\n\n`procsd exec` requres all the environment variables defined in `environment` section of `procsd.yml` config file.\n\nSometimes in development mode you need different environment configuration. For that you can add additional environment section `dev_environment` and require it as well using `--dev` flag, example:\n\n```yaml\napp: sample_app\nenvironment:\n  PORT: 2501\n  RAILS_ENV: production\n  RAILS_LOG_TO_STDOUT: true\ndev_environment:\n  RAILS_ENV: development\n  SOME_OTHER_DEV_ENV_VARIABLE: value\n```\n\n```\n# Run web process with all environment \u0026 dev_environment variables included:\n\ndeploy@server:~/sample_app$ procsd exec web --dev\n```\n\n\u003e In case if `dev_environment` has env variable with the same name like in `environment`, this variable will be rewritten with value from `dev_environment`.\n\n\n### Nginx integration (with automatic HTTPS)\n\u003e Before make sure that you have Nginx installed `sudo apt install nginx` and running `sudo systemctl status nginx`.\n\nIf one of your application processes is a web process, you can automatically setup Nginx (reverse proxy) config for it. Why? For example to serve static files (assets, images, and all other files located in `public` folder or another customly defined folder) directly using fast Nginx, rather than application server. Or to enable SSL support (see below).\n\nAdd to your procsd.yml `nginx` section with `server_name` option defined:\n\n\u003e If you don't have a domain for an application (or don't need it), you can add server IP instead: `server_name: 159.159.159.159`.\n\n\u003e If your application use multiple domains/subdomains, add all of them separated with space: `server_name: my-domain.com us.my-domain.com uk.my-domain.com`\n\n```yaml\napp: sample_app\nprocesses:\n  web: bundle exec rails server -p $PORT\n  worker: bundle exec sidekiq -e $RAILS_ENV\nformation: web=1,worker=2\nenvironment:\n  PORT: 2501 # PORT will be used by Nginx to proxy requests from 0.0.0.0:80/443 to 127.0.0.1:PORT (required)\n  HOST: localhost # Make sure that your application server in production running on 127.0.0.1, not 0.0.0.0\n  RAILS_ENV: production\n  RAILS_LOG_TO_STDOUT: true\nnginx:\n  server_name: my-domain.com\n  public_folder_path: public # path is relative to the main project directory, default value is `public`.\n```\n\nConfiguration is done! Run [procsd create](#create-an-application-export-to-systemd) to create app services with Nginx reverse proxy config:\n\n```\ndeploy@server:~/sample_app$ procsd create\n\nCreating app units files in the systemd directory (/etc/systemd/system)...\nCreate: /etc/systemd/system/sample_app-web.1.service\nCreate: /etc/systemd/system/sample_app-worker.1.service\nCreate: /etc/systemd/system/sample_app-worker.2.service\nCreate: /etc/systemd/system/sample_app.target\nReloaded configuraion (daemon-reload)\nCreated symlink /etc/systemd/system/multi-user.target.wants/sample_app.target → /etc/systemd/system/sample_app.target.\nEnabled app target sample_app.target\nApp services were created and enabled. Run `start` to start them\nCreating Nginx config (/etc/nginx/sites-available/sample_app)...\nCreate: /etc/nginx/sites-available/sample_app\nLink Nginx config file to the sites-enabled folder...\nNginx config created and daemon reloaded\n```\n\n\u003cdetails\u003e\n  \u003csummary\u003e/etc/nginx/sites-available/sample_app\u003c/summary\u003e\n\n```\nupstream sample_app {\n  server 127.0.0.1:2501;\n}\n\nserver {\n  listen 80;\n  listen [::]:80;\n\n  server_name my-domain.com;\n  root /home/deploy/sample_app/public;\n\n  location ^~ /assets/ {\n    gzip_static on;\n    expires max;\n    add_header Cache-Control public;\n  }\n\n  try_files $uri/index.html $uri @sample_app;\n  location @sample_app {\n    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n    proxy_set_header Host $http_host;\n    proxy_set_header X-Forwarded-Proto $scheme;\n    proxy_set_header X-Real-IP $remote_addr;\n    proxy_redirect off;\n    proxy_pass http://sample_app;\n  }\n\n  client_max_body_size 256M;\n  keepalive_timeout 60;\n  error_page 500 502 503 504 /500.html;\n  error_page 404 /404.html;\n  error_page 422 /422.html;\n}\n```\n\u003c/details\u003e\u003cbr\u003e\n\nEverything is done. Start app services (`procsd start`) and go to `http://my-domain.com` where you'll see your application proxying with Nginx.\n\n#### Auto SSL using Certbot\n\nTo generate Nginx config with free SSL certificate (from [Let’s Encrypt](https://letsencrypt.org/)) included, you need to install [Certbot](https://certbot.eff.org/) on the remote server first. For Ubuntu 18.04 (check here instructions for other versions https://certbot.eff.org/lets-encrypt/ubuntufocal-nginx):\n\n```bash\n$ sudo apt install software-properties-common\n$ sudo add-apt-repository ppa:certbot/certbot\n$ sudo apt update\n$ sudo apt install certbot python-certbot-nginx\n```\n\n\u003e When you install certbot, it automatically setup a cron job (twice per day) to renew expiring certificates ([Automated Renewals](https://certbot.eff.org/docs/using.html#automated-renewals)), so you don't have to worry about renewing certificates manually.\n\nThen update procsd.yml by adding `ssl: true`:\n\n```yml\n# ...\nnginx:\n  server_name: my-domain.com\n  ssl: true # added\n```\n\nConfiguration is done. **Make sure that all domains defined in procsd (nginx.server_name) are pointing to the server IP** where application is hosted. Then run `procsd create` _(you will probably need first run `procsd destroy` if app services already exists)_ as usual:\n\n\u003e By default Certbot obtaining certificate from _Let's Encrypt_ without a contact email. If you want to provide contact email, define env variable `CERTBOT_EMAIL` with your email in the `.env` file.\n\n\u003cdetails/\u003e\n  \u003csummary\u003eOutput\u003c/summary\u003e\n\n```\ndeploy@server:~/sample_app$ procsd create\n\nCreating app units files in the systemd directory (/etc/systemd/system)...\nCreate: /etc/systemd/system/sample_app-web.1.service\nCreate: /etc/systemd/system/sample_app-worker.1.service\nCreate: /etc/systemd/system/sample_app-worker.2.service\nCreate: /etc/systemd/system/sample_app.target\nReloaded configuraion (daemon-reload)\nCreated symlink /etc/systemd/system/multi-user.target.wants/sample_app.target → /etc/systemd/system/sample_app.target.\nEnabled app target sample_app.target\nApp services were created and enabled. Run `start` to start them\nCreating Nginx config (/etc/nginx/sites-available/sample_app)...\nCreate: /etc/nginx/sites-available/sample_app\nLink Nginx config file to the sites-enabled folder...\nNginx config created and daemon reloaded\n\nExecute: sudo certbot --agree-tos --no-eff-email --non-interactive --nginx -d my-domain.com --register-unsafely-without-email\nSaving debug log to /var/log/letsencrypt/letsencrypt.log\nPlugins selected: Authenticator nginx, Installer nginx\nObtaining a new certificate\nPerforming the following challenges:\nhttp-01 challenge for my-domain.com\nWaiting for verification...\nCleaning up challenges\nDeploying Certificate to VirtualHost /etc/nginx/sites-enabled/sample_app\nRedirecting all traffic on port 80 to ssl in /etc/nginx/sites-enabled/sample_app\n\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\nCongratulations! You have successfully enabled https://my-domain.com\n\nYou should test your configuration at:\nhttps://www.ssllabs.com/ssltest/analyze.html?d=my-domain.com\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\nIMPORTANT NOTES:\n - Congratulations! Your certificate and chain have been saved at:\n   /etc/letsencrypt/live/my-domain.com/fullchain.pem\n   Your key file has been saved at:\n   /etc/letsencrypt/live/my-domain.com/privkey.pem\n   Your cert will expire on 2019-02-17. To obtain a new or tweaked\n   version of this certificate in the future, simply run certbot again\n   with the \"certonly\" option. To non-interactively renew *all* of\n   your certificates, run \"certbot renew\"\n - Your account credentials have been saved in your Certbot\n   configuration directory at /etc/letsencrypt. You should make a\n   secure backup of this folder now. This configuration directory will\n   also contain certificates and private keys obtained by Certbot so\n   making regular backups of this folder is ideal.\n - If you like Certbot, please consider supporting our work by:\n\n   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate\n   Donating to EFF:                    https://eff.org/donate-le\n\nSuccessfully installed SSL cert using certbot\n```\n\u003c/details\u003e\u003cbr\u003e\n\nThat's it. Start app services (`procsd start`) and go to `https://my-domain.com` where you'll see your application proxying with Nginx and SSL enabled.\n\n\n\u003cdetails/\u003e\n  \u003csummary\u003eNote about using Cloudflare CDN\u003c/summary\u003e\u003cbr\u003e\n\nIf you use Cloudflare CDN, that means the process of obtaining Let's Encrypt SSL Certificate will fail. To fix it, install `python-certbot-dns-cloudflare` package:\n\n```bash\n$ sudo apt install certbot python-certbot-dns-cloudflare\n```\n\nRead instructions [here how to get Cloudflare API Token and obtain certificates](https://certbot-dns-cloudflare.readthedocs.io/en/stable/). In short,\n\n**1)** Go to https://dash.cloudflare.com/profile/api-tokens and [get your API Token](https://support.cloudflare.com/hc/en-us/articles/200167836-Where-do-I-find-my-Cloudflare-API-key-).\n\n**2)** Create on the server `~/.secrets/certbot/` directory with `cloudflare.ini` file inside:\n\n```bash\n$ mkdir -p ~/.secrets/certbot/\n$ chmod 0700 ~/.secrets/\n$ touch ~/.secrets/certbot/cloudflare.ini\n$ chmod 0400 ~/.secrets/certbot/cloudflare.ini\n```\n\n**3)** Put inside `cloudflare.ini` file your Cloudflare token:\n\n```bash\n$ sudo nano ~/.secrets/certbot/cloudflare.ini\n```\n\n```bash\n# ~/.secrets/certbot/cloudflare.ini\n\n# Cloudflare API token (example) used by Certbot:\ndns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567\n```\n\n**4)** Obtain certificates for all your domains declared in `procsd.yml` using _certbot-dns-cloudflare_ plugin:\n\n```bash\n# Example command for my-domain.com domain:\n\n$ sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials ~/.secrets/certbot/cloudflare.ini -d my-domain.com\n```\n\n**5)** If all went fine, update Nginx application config with new certificates (using certbot command). To get required certbot command type `$ procsd config certbot_command`, then execute it:\n\n```bash\n# Example command for my-domain.com domain:\n\n$ sudo certbot --agree-tos --no-eff-email --redirect --non-interactive --nginx -d my-domain.com --register-unsafely-without-email\n```\n\nAll is done!\n\n\u003c/details\u003e\u003cbr\u003e\n\n\n## All available commands\n\n```\n$ procsd --help\n\nCommands:\n  procsd create          # Create and enable app services\n  procsd destroy         # Stop, disable and remove app services\n  procsd start           # Start app services\n  procsd stop            # Stop app services\n  procsd restart         # Restart app services\n  procsd enable          # Enable app target\n  procsd disable         # Disable app target\n  procsd logs            # Show app services logs\n  procsd status          # Show app services status\n  procsd list            # List all app services\n  procsd exec            # Run single app process with environment\n  procsd config          # Print config files based on current settings. Available types: sudoers, services, certbot_command\n  procsd help [COMMAND]  # Describe available commands or one specific command\n  procsd --version, -v   # Print the version\n```\n\n\n## Difference with Foreman\n\n[Foreman](http://ddollar.github.io/foreman/) itself designed for _development_ (not production) usage only and doing it great. Yes, Foreman allows to [export](http://ddollar.github.io/foreman/#EXPORTING) Procfile to the Systemd, but that's all. After export you have to manually use `systemctl` and `journalctl` to manage/check exported services. Procsd not only exports application, but provides [simple commands](#all-available-commands) to manage exported target.\n\n* Foreman systemd export uses [dymamic](https://fedoramagazine.org/systemd-template-unit-files/) services templates and as a result generates quite a lot of files/folders in the systemd directory even for a simple application.\n\n* Services generated using Foreman contain [$PORT variable](http://ddollar.github.io/foreman/#PROCFILE) in their names (and it's [undocumented](http://ddollar.github.io/foreman/#SYSTEMD-EXPORT) logic). For example for Procfile and formation `web=1,worker=2` (from example above), exported services with Foreman will be: `sample_app-web@2500.service`, `sample_app-worker@2600.service` and `sample_app-worker@2601.service`. My opinion about this approach: it's complicated. Why is there required PORT variable in the services names? Procsd following one rule: simplicity. For export it uses static service files (that means for each process will be generated it's own service file) and services names have predictable, Heroku-like names.\n\n* Procsd export can provide additional stop/restart commands for each service (see _Notes_ below).\n\n* To delete existing app services from Systemd, there is `procsd destroy` command. It is doing the following: stop services if they are running, delete all required systemd files from systemd directory, and restart systemd (`daemon-reload`). This command especially useful while testing, when you need frequently create/update configuration.\n\n\n## Notes\n\n* If you want to set environment variables per process, [use format](https://github.com/ddollar/foreman/wiki/Per-Process-Environment-Variables) like Foreman recommends.\n\n* To print commands before execution, provide env variable `VERBOSE=true` before procsd command. Example:\n\n```\ndeploy@server:~/sample_app$ VERBOSE=true procsd logs -n 3\n\nExecute: journalctl --no-pager --no-hostname --all --output short-iso -n 3 --unit sample_app-*\n\n-- Logs begin at Sun 2018-10-21 00:38:42 +04, end at Sun 2018-11-04 19:17:01 +04. --\n2018-11-04T19:11:59+0400 sample_app-worker.2[29907]: 2018-11-04T15:11:59.597Z 29907 TID-gne5aeyuz INFO: Upgrade to Sidekiq Pro for more features and support: http://sidekiq.org\n2018-11-04T19:11:59+0400 sample_app-worker.2[29907]: 2018-11-04T15:11:59.597Z 29907 TID-gne5aeyuz INFO: Booting Sidekiq 5.2.2 with redis options {:id=\u003e\"Sidekiq-server-PID-29907\", :url=\u003enil}\n2018-11-04T19:11:59+0400 sample_app-worker.2[29907]: 2018-11-04T15:11:59.601Z 29907 TID-gne5aeyuz INFO: Starting processing, hit Ctrl-C to stop\n```\n\n* You can use extended format of processes commands inside `procsd.yml` to provide additional restart/stop commands for each process:\n\n\u003e All possible options: [ExecStart](https://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStart=) (default command to start a process), [ExecReload](https://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecReload=), and [ExecStop](https://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStop=).\n\n\u003e If procsd.yml has `processes:` option defined, then content of Procfile (if it exists) will be ignored.\n\n```yml\napp: sample_app\nprocesses:\n  web:\n    ExecStart: bundle exec rails server -p $PORT\n    ExecReload: bundle exec pumactl phased-restart\n  worker: bundle exec sidekiq -e production\n```\n\nWhy? For example default Ruby on Rails application server [Puma](http://puma.io/) supports [Phased or Rolling restart](https://github.com/puma/puma/blob/master/docs/restart.md#normal-vs-hot-vs-phased-restart) feature. If you provide separate `ExecReload`command for a process, then this command will be called while executing `$ procsd restart` by systemd instead of just killing and starting process again.\n\n* Another option you can provide for each process is [RuntimeMaxSec](https://www.freedesktop.org/software/systemd/man/systemd.service.html#RuntimeMaxSec=). It is used to automatically restart a process every N period of time. Could be useful for worker types of processes (like Sidekiq) where process memory could increase while running:\n\n\u003e Example values for RuntimeMaxSec: `30s` (30 seconds), `5m` (5 minutes), `3h` (3 hours), `1d` (1 day).\n\n```yml\napp: sample_app\nprocesses:\n  web:\n    ExecStart: bundle exec rails server -p $PORT\n    RuntimeMaxSec: 12h\n```\n\n* If you use Nginx integration but default Nginx requests timeout (60s) is too small for you, [you can set a custom timeout](https://serverfault.com/a/777753) in the global Nginx config.\n\n\n## Capistrano integration\n\nhttps://github.com/vifreefly/capistrano-procsd\n\n\n## ToDo\n* Add `procsd update` command to quickly update changed configuration (application units, nginx config, etc), instead of calling two separate commands (`procsd destroy` and `procsd create`)\n\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n","funding_links":[],"categories":["Ruby","cli"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvifreefly%2Fprocsd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvifreefly%2Fprocsd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvifreefly%2Fprocsd/lists"}