Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add systemd unit file #1716

Closed

Conversation

noahwilliamsson
Copy link

What does this PR do and why is it necessary?

This PR adds a systemd unit file to allow OctoPrint to be started at boot time in a modern Linux distribution that runs the systemd init system. The unit file's defaults are suitable for the instructions provided in Setup on a Raspberry Pi running Raspbian

It tries to be backwards compatible with the existing init script with respect to envs defined in/etc/default/octoprint, although a few of them (OCTOPRINT_USER, DAEMON, NICE and UMASK) were not possible to support in the unit file. See the unit file for instructions on howto override these.

OctoPrint already comes with a SysV and Debian-style init script and configuration template. These work fine, even in a systemd world. But since most modern Linux distributions have moved over to systemd, I figured a systemd unit file would be a more proper way of doing things moving forward.

That way new OctoPrint users, some of who perhaps come in contact with Linux for the first time, don't unnecessarily get "exposed" to the old (and in the future, perhaps deprecated) way of adding boot services, but instead get to learn the modern way with systemctl (and journalctl for debugging) right from the start.

How was it tested? How can it be tested by the reviewer?

# Disable old OctoPrint init script
sudo service octoprint stop
sudo update-rc.d -f octoprint remove || true
sudo mv /etc/init.d/octoprint /etc/init.d/octoprint-old || true
sudo mv /etc/default/octoprint /etc/default/octoprint-old || true

# Install new OctoPrint init script
sudo cp scripts/octoprint.service /etc/systemd/system
sudo systemctl daemon-reload
sudo systemctl enable octoprint
sudo systemctl start octoprint
sudo systemctl status octoprint
sudo journalctl -u octoprint
ps auxw|grep -i octoprint

# Test change port via /etc/default/octoprint
echo PORT=1234 |sudo tee -a /etc/default/octoprint
sudo systemctl restart octoprint
ps auxw|grep -i octoprint

Any background context you want to provide?

What are the relevant tickets if any?

Screenshots (if appropriate)

Further notes

  • Debian Jessie (8.0) supports systemd
  • Raspbian Jessie was released in sept, 2015
  • The older Debian Wheezy (7.0) and Raspbian Wheezy does not support systemd

Like the author of the current init script, some helpful instructions are provided at the top of the file. They may serve as a starting point if the instructions in the wiki should be updated aswell.

# -2 ensures Octoprint has a slight priority over user processes.
Nice=-2

ExecStart=/home/pi/OctoPrint/venv/bin/octoprint serve --basedir ${BASEDIR} --config ${CONFIGFILE} --port ${PORT} --foobar $DAEMON_ARGS"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--foobar? O_o

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another thing here - I guess it's not possible to leave --config, --basedir and --port out unless the corresponding environment variables are set? The defaults in octoprint.defaults are what OctoPrint would automatically use unless overridden via command line.

@foosel
Copy link
Member

foosel commented Jan 19, 2017

Thanks! Just did a quick review and added two comments, could you take a look at those? Cheers!

@noahwilliamsson
Copy link
Author

O_o indeed. --foobar was something I used to test the failure mode. Obviously I shouldn't have committed this. Thanks for catching it, I'll update the PR.

Regarding the always present --config, --basedir and friends, I'd say this is as good as it gets if you want backwards compatibility with the existing script, and also assume most people use OctoPrint in a Raspberry Pi environment.

If you would be willing to ignore the current /etc/defaults/octoprint
I suppose you could make it slighly cleaner by using something like ExecStart=/home/pi/OctoPrint/venv/bin/octoprint serve $DAEMON_ARGS instead.

$FOO (as opposed to ${FOO}) will expand in a way that will make DAEMON_ARGS="--port 1234 --basedir /tmp/octoprint" do what you expect. (Also, note that the first argument to ExecStart= cannot be a variable).

Googling systemd variable expansion suggests it might be possible to do fancy variable expansion by involving one or more instances of bash. But by now you'd be roaming into ridiculous territory..

@foosel
Copy link
Member

foosel commented Feb 16, 2017

I just realized I hadn't gotten back to you here, sorry for that. I was out sick the last two weeks and am still playing catch up with everything that accumulated during that time.

I agree, we don't want to overengineer this...

If I understand the general approach to customizing systemd service files correctly, you usually don't really use the /etc/default approach anymore but instead utilize systemctl edit <service> to define the necessary overrides, right? In that case I'd actually go with getting rid of the dependency on that and the associated backwards compatibility to customization of the initscript - if someone decides on switching to using the systemd file instead of the initscript it's a conscious decision involving manual steps, and in that case the user should hopefully know that stuff gets configured differently.

So in that case I'd say having it instead be ExecStart=/home/pi/OctoPrint/venv/bin/octoprint serve $DAEMON_ARGS should be fine and also be more flexible in the long term. Do you want to adjust that accordingly? If not (e.g. no time considering how long I've left that waiting 😳), I'll do it as part of the merge, no problem.

@foosel
Copy link
Member

foosel commented Mar 9, 2017

@noahwilliamsson still waiting for an answer here :)

@depau
Copy link
Contributor

depau commented May 17, 2017

I think this would be way better with optional systemd socket activation (optional because it would break plugins like OctoPrint-Telegram).
I also think some auto-restart on failure lines would be good. This is what I use:

Restart=on-failure
RestartSec=5

I also don't like the fact that paths are hardcoded to ~pi, but that's another thing though. I don't really like the way OctoPrint sets itself up in the filesystem, but that's not the point of this PR. I may open an issue to talk about this, maybe.

@Lewiscowles1986
Copy link

I think this should be a user-service file rather than tied to pi user.

Benefits

  • Sudo access is not needed to administer.
  • So long as you keep to virtualenv and port 5000 (defaults) the systemd service file should have no problems.
  • can setup other user-profiles for admin, non-octoprint etc

https://gist.github.com/Lewiscowles1986/5ecfc1f4125a7e6a39006cbb7d69229a

Linked a Gist (just published) from the build I made for my BiL last week using user. It's much more basic, but essentially runs octoprint.

instead of /etc/systemd/system/octoprint.service it lives in ~/.config/systemd/user/octoprint.service

  • uses --user flags to systemctl
  • uses /opt/OctoPrint
systemctl --user enable octoprint
systemctl --user start octoprint
systemctl --user status octoprint.service

@noahwilliamsson
Copy link
Author

@Lewiscowles1986 I'm afraid user services only starts once the user logs in, and are killed when the user logs out. So it would only work if you've configured your Raspberry Pi installation to automatically login during boot.

@depau
Copy link
Contributor

depau commented Sep 18, 2017 via email

@Lewiscowles1986
Copy link

Lewiscowles1986 commented Sep 18, 2017

@noahwilliamsson well if a user is not logged in (btw default for jessie and stretch gui is to have user pi logged in automatically) you wouldn't want them running octoprint, that's kinda the point, to isolate it to run under one user, only when they are using GUI. The specific setup I used this for was standard stock pi with a kiosk user-service so that octoprint would always be running as long as network service was started. Unless someone specifically disabled pi autologin you can have multi-user and have octoprint running.

@nophead
Copy link
Contributor

nophead commented Sep 18, 2017 via email

@Lewiscowles1986
Copy link

I built octoprint from repo and install only. Probably why there is a difference.

  • didn't fancy being stuck on Jessie
  • don't trust disk-image distro's for single app's.
  • might want to install other things like a kanban as another user, have that boot to kiosk too, so that it's a less single-dimensional system.

Each to their own I suppose. I'd still say the single user makes more sense, but regardless networking.target would be sensible if you're running headless

@noahwilliamsson
Copy link
Author

@Lewiscowles1986 While it might be the case that automatic login is turned on by default on Raspbian Stretch with Desktop it most certainly isn't on most Linux distributions, including Raspbian Jessie Lite.

I understand that for your particular use case, it is sufficient if OctoPrint is running only when the user is logged in with a desktop session on the Raspberry Pi. However, some people might have a different setup with a headless computer (e.g., a Raspberry Pi running Raspbian Stretch Lite) permanently connected to their printer in order to provide remote access to the printer via OctoPrint's API or web GUI.

I do like the fact that non-privileged users can manage their own services with systemd but in this case I don't think it's a good fit. Sorry.

@Lewiscowles1986
Copy link

Lewiscowles1986 commented Sep 18, 2017

okay, but that aside the [Unit] would benefit even more from After=network.target so that the network has initialised right?

Btw I have no dog in this, I'm totally borrowing parts of your systemD file to enhance my rather rushed and cobbled together attempt.

At the same time, I'd like to understand what the sane defaults are and why they are 👍

@bzed
Copy link
Contributor

bzed commented Oct 8, 2017

@noahwilliamsson @Lewiscowles1986 It is possible to configure systemd to allow user daemons to be started and stopped as all other units handled by systemd. But thats much more complicated to configure than to install the service as root. But at the end its the same file, so if a user knows how to setup systemd linger for users, he will know how to install the service, too.

(And especially on Jessie configuring that is an extra pain as there are some files missing and dbus needs to be configured, too)

@Lewiscowles1986
Copy link

@bzed it's not about what the user knows, it's about access. The entire program should be able to run after install for any user that belongs to the right groups, regardless of root access IMO. As I'm not largely involved I don't really expect my opinion to count for alot, but just saying "users must know how to manage systemd" misses the point.

@foosel
Copy link
Member

foosel commented Oct 9, 2017

It's a server program, I think assuming a system wide install under its own user as the default scenario is fair game (and also in line with the SysV initscript this service file is supposed to replace.

@koenkooi
Copy link
Contributor

koenkooi commented Dec 2, 2017

FWIW, this is the unit file I use:

[Unit]
Description=The responsive web interface for your 3D printer

[Service]
User=octoprint
Type=simple
ExecStart=/usr/bin/octoprint --config /etc/octoprint/config.yaml

[Install]
WantedBy=basic.target

@foosel
Copy link
Member

foosel commented Dec 19, 2018

Sadly never got an answer to the open question and still lack the experience with systemd to answer it myself. Closing 😕

@foosel foosel closed this Dec 19, 2018
foosel added a commit that referenced this pull request Dec 19, 2018
As discussed in #1716
@bzed
Copy link
Contributor

bzed commented Dec 19, 2018

@foosel I missed that question, but... Using /etc/default is like using a paper phone book with your android mobile phone. Systemd has various ways to extend and override a given service, there is no need to stay with old init.d stuff (which is supported for compatibility reasons...).

tedder pushed a commit to tedder/OctoPrint that referenced this pull request Dec 23, 2018
@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 28, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants