Setting up a simple systemd service
Disclaimer: Not an expert on either systemd or ansible, but this is something I
may need to do again...
Recently I needed to test an haproxy setup with a service running on an
arbitrary port. I didn't need anything fancy so decided to go with python's
inbuilt http server.
This is a module that lets you serve the files in a directory over http.
From the command line something like:
python3 -m http.server 9999
That will run a server in the current working directory as the current user.
I needed to run this on several servers configured via ansible. These are RHEL 8
cloud image based servers.
The task ended up looking like:
- name: 130 - Copy systemd service file to server (7/23)
become: yes
ansible.builtin.template:
src: files/templates/simple-http.service.j2
dest: /etc/systemd/system/simple-http.service
owner: root
group: root
- name: 140 - Simple HTTP Service (8/23)
become: yes
systemd:
name: simple-http
state: started
daemon_reload: yes
enabled: yes
These two tasks place a service file in the /etc/systemd/system directory and
then start the service. I've specified daemon_reload to make sure any changes to
the service file get picked up. In theory not necessary if you get the service
file exactly right the first time, but I didn't and then spent some time
wondering why my changes weren't being applied.
The service file template is:
[Unit]
Description=Simple http server for testing haproxy
After=multi-user.target
[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/python3 -m http.server {{ha_backend_test_port}}
WantedBy=multi-user.target
WorkingDirectory=/home/cloud-user/
This defines a service that runs as root (not a good idea anywhere but a test
environment that you can guarantee no untrusted users can access). The service
runs in the cloud-user's home directory and will serve up an index.html file
that ansible drops into that directory (without that index.html the server would
list the files in the directory).
Next improvement to this will involve running this a less privileged user.
Noting that cloud-user itself is not ideal because it has access to passwordless
sudo. Not that there should be much chance of using http.server as an attack
vector, but best to not make it any easier than we have to.
The parameter ha_backend_test_port is an ansible variable to set the actual
port.
Testing this works is as simple as:
curl http://backend-01.example.com:8888
<html>
<head>
<title>Index</title>
</head>
<body>
<h1>backend-01.example.com</h1>
</body>
</html>
Assuming we specified 8888 as the ha_backend_test_port in our ansible.