Running HTTP server in EC2 using Systemd
So today while deploying a Golang HTTP server in EC2 instance with Amazon AMI (built on top of Fedora distro of Linux OS), I hit an interesting roadblock. I copied the Go executable into the server and executed it over SSH and everything worked fine. But when I closed the SSH connection the website went down. I had deployed web servers in Docker based environments but this was the first time I was setting up a VM. Then realized that I needed it to run as a service daemon, so that it will be spawned even if the server crashed or the EC2 instance restarted.
One Possible Solution
Upon quick googling I stumbled upon Linux service manager called
systemd. As an added bonus Fedora comes with
systemd installed by default, so I thought lets use it.
Wikipedia page describes
The systemd software suite provides fundamental building blocks for a Linux operating system. It includes the systemd “System and Service Manager”, an init system used to bootstrap user space and manage user processes.
On each Unix system, there is one process called
init process or PID 1, which is the first process started by the kernel.It is the direct or indirect parent of all processes, and it replaces the parent of a process when the original parent terminates. Due to this, it can do lot of things that other process can’t such as spawning up and maintaining userspace during boot and is well suited for the purpose of monitoring daemons.
systemd runs as a PID 1 and is responsible of starting and managing services and daemons, logging, running containers and VMs, and lots more.
systemd performs its startup tasks in parallel and uses unix-sockets and d-bus for IPC communication.
The core components of
systemd: is the Linux service manager
systemctl: is basically a part of
systemdwhich provides ability to interact with and control the state of
systemdservice manager. Linux
servicecommand is a wrapper around systemctl command depending the OS distro.
systemd-analyze: used to analyze the performance statistics and tracing information retrieved from
systemd suite provides other components such as
journald (event logging and log file daemon),
logind (daemon for managing user logins),
timedated (daemon for controlling datetime settings) and many more.
systemctl start [name.service]: start a service
systemctl stop [name.service]: stop a service
systemctl restart [name.service]: restart a service
systemctl reload [name.service]: reload the service config from its
systemctl status [name.service]: check the status of the service
systemctl is-active [name.service]: check whether the service is active or not.
systemctl list-units --type service --all: lists all active services
- I built the Go server executable for linux environment using command
env GOOS=linux GOARCH=amd64 go build -o hello-webfrom my mac.
- Create a file called
/etc/systemd/system/hello-web.servicehaving following content:
[Unit] Description=hello-web [Service] Environment=SYSTEMD_LOG_LEVEL=debug Type=simple Restart=always RestartSec=5s WorkingDirectory=/home/ec2-user/projects/hello-web ExecStart=/home/ec2-user/projects/hello-web/hello-web -debug=true
hello-web is a Go executable for an HTTP server that we want to run as a daemon.
WorkingDirectory defines on which directory the service will be launched.
NOTE: Not providing
WorkingDirectory may lead to unexpected errors and consequences such as relative path not working as expected. I learnt it the hard way.
sudo systemctl start hello-web.service.
.servicecan be ignored as its the default extension while working with systemctl. This command is equivalent of
sudo service hello-web start
- After making any changes to service file
hello-web.service, we must run
sudo systemctl daemon-reload
- To check the status of the service, execute
systemctl status hello-web.service
- In case the service deoesn’t start, get the PID of the failed process and use
journaldto check the error logs:
journalctl _PID=<YOUR_PID>. This is how I got to know about relative path issue which was fixed by setting
WorkingDirectoryin service file.
I have almost always deployed my service using services like Docker, Kubernetes and other container platforms. But I today learnt something
new way to deploy services using EC2 and
systemd. I will play around to learn more about
systemd and similar tools. If you have any suggestions or improvements, it is more than welcome.
- Wikipedia page
- Digital Ocean tutorials: Systemd essentials
- Medium blog: Creating a Linux service with systemd