DEV Community

Cover image for Never Let Your VMs Play Dead: How Linux Services Saved My Automation from Sudden Death๐Ÿง
Haripriya Veluchamy
Haripriya Veluchamy

Posted on

Never Let Your VMs Play Dead: How Linux Services Saved My Automation from Sudden Death๐Ÿง

Hey there, Linux beginners! ๐Ÿ‘‹ Today we're going to make Linux services super easy to understand, focusing on how to run your Node.js web applications reliably and automatically.

Why I Wrote This Blog ๐Ÿ’ก

Let me share something that happened to me recently. I set up some Azure DevOps self-hosted agents and GitHub webhook automation on what should have been "always-on" VMs. Everything worked perfectly while I was logged in, but the moment I logged off? Complete system failure! All my carefully configured automation just... stopped.

That's when I realized I needed to learn about Linux services. Without proper service configuration, processes you start manually will shut down when you log out. This caused me a lot of headaches and downtime before I figured out the solution.

If you're facing similar issues or want to avoid them altogether, this guide is for you.

The Master and Worker: Understanding systemd and Services ๐Ÿค”

Let's start with a simple way to think about Linux services:

Think of it like a workplace:

  • systemd is the master (the boss) - It oversees everything, gives orders, and makes sure all the work gets done
  • Services are the workers - Each worker has a specific job to do and follows the boss's instructions

In more technical terms:

systemd (the master):

  • Is the main controller of your Linux system
  • Starts and stops services
  • Makes sure services restart if they crash
  • Keeps track of what each service is doing
  • Manages the startup process when your computer boots

Services (the workers):

  • Are programs that run in the background
  • Each performs a specific task (like running a web server)
  • Run continuously, even when you're not logged in
  • Don't have a user interface - they just do their job quietly

Why Using Services is Better Than Manual Work ๐ŸŒŸ

Imagine you have a Node.js web application. You could:

Option 1: Run it manually (the hard way)

node app.js
Enter fullscreen mode Exit fullscreen mode

But then:

  • If you close your terminal, your app stops ๐Ÿ˜ฑ
  • If your app crashes, it stays down until you restart it ๐Ÿ’”
  • After rebooting your computer, you have to remember to start it again โฐ
  • It's easy to make mistakes when starting it manually ๐Ÿคฆโ€โ™‚๏ธ

Option 2: Create a service (the smart way)

  • It starts automatically when your computer boots ๐Ÿš€
  • If it crashes, systemd automatically restarts it ๐Ÿ”„
  • It keeps running even when you're not logged in ๐Ÿƒโ€โ™‚๏ธ
  • You manage it with simple commands โŒจ๏ธ

That's why the meme shows disapproval for "Running program Manually" and approval for "Use linux service"!

Understanding Linux Links Before We Start ๐Ÿ”—

Before creating a service, let's quickly understand two helpful Linux concepts: soft links and hard links.

Soft Links (Symbolic Links) ๐Ÿช„

A soft link is like a shortcut to a file or folder.

Real-life example: It's like a sign pointing to a restaurant. The sign isn't the restaurant - it just tells you where to find it.

To create a soft link:

ln -s /path/to/original/file /path/to/link
Enter fullscreen mode Exit fullscreen mode

Example:

ln -s /home/user/my-nodejs-app/config.json /home/user/Desktop/app-config.json
Enter fullscreen mode Exit fullscreen mode

Now you can edit the config file from your desktop!

Important: If you delete the original file, the link becomes useless.

Hard Links ๐Ÿ”จ

A hard link is like having the same file exist in two places at once.

Real-life example: Imagine if you could have the exact same pizza exist in both the kitchen and living room simultaneously. Take a bite in either location, and that bite disappears from both places because they're actually the same pizza!

To create a hard link:

ln /path/to/original/file /path/to/hardlink
Enter fullscreen mode Exit fullscreen mode

Example:

ln /home/user/my-nodejs-app/important-data.json /home/user/backups/important-data.json
Enter fullscreen mode Exit fullscreen mode

Key things to know:

  • They only work for files (not folders)
  • They must be on the same disk/filesystem
  • If you delete one link, the file still exists through the other link
  • Changes to either file affect both because they're actually the same file

Creating a Service for Your Node.js Application ๐Ÿ› ๏ธ

Now let's create a service file for your Node.js application:

1. Create a Service File

First, we'll create a file that tells systemd (the master) how to run your Node.js app (the worker):

sudo nano /etc/systemd/system/my-nodejs-app.service
Enter fullscreen mode Exit fullscreen mode

2. Configure Your Service

Copy and paste this template, then update the parts in CAPS with your information:

[Unit]
Description=My Amazing Node.js Application
After=network.target

[Service]
# The user that will run the application
User=YOUR_USERNAME
# Where your app is located
WorkingDirectory=/home/YOUR_USERNAME/YOUR_APP_FOLDER
# The command to start your app
ExecStart=/usr/bin/node app.js
# Restart if it crashes
Restart=always
# Wait 10 seconds before restart
RestartSec=10
# App environment variables
Environment=NODE_ENV=production
Environment=PORT=3000

[Install]
WantedBy=multi-user.target
Enter fullscreen mode Exit fullscreen mode

Let's explain what each section means in simple terms:

[Unit] Section

  • Description: A simple name for your app
  • After: Tells systemd to start this service after the network is ready

[Service] Section

  • User: Which user account should run this app (never use root for security!)
  • WorkingDirectory: The folder where your app lives
  • ExecStart: The exact command to start your app
  • Restart: Tells systemd to restart your app if it crashes
  • RestartSec: How many seconds to wait before restarting
  • Environment: Any environment variables your app needs

[Install] Section

  • WantedBy: When this service should start (multi-user.target means normal boot)

3. Enable and Start Your Service

Now let's tell systemd (the master) about your new service (worker):

# Reload systemd so it sees your new service file
sudo systemctl daemon-reload

# Enable your service to start automatically when the computer boots
sudo systemctl enable my-nodejs-app

# Start your service right now
sudo systemctl start my-nodejs-app
Enter fullscreen mode Exit fullscreen mode

Service Management Made Simple ๐ŸŽฎ

Here are easy commands to manage your service:

# Check if your service is running
systemctl status my-nodejs-app

# Stop your service
sudo systemctl stop my-nodejs-app

# Start your service
sudo systemctl start my-nodejs-app

# Restart your service (useful after code changes)
sudo systemctl restart my-nodejs-app

# Disable automatic startup on boot
sudo systemctl disable my-nodejs-app
Enter fullscreen mode Exit fullscreen mode

Checking Your Service Logs ๐Ÿ“‹

When something goes wrong, you can see the logs:

# View all logs for your service
journalctl -u my-nodejs-app

# View only the most recent logs (last 50 lines)
journalctl -u my-nodejs-app -n 50

# Follow the logs in real-time (like watching for new messages)
journalctl -u my-nodejs-app -f
Enter fullscreen mode Exit fullscreen mode

Putting It All Together: A Practical Example ๐Ÿงฉ

Let's say you have a simple Node.js weather app that you want to run as a service:

  1. Your app is in /home/weather-user/weather-app/
  2. It starts with node server.js
  3. It needs to run on port 3000

Here's what you would do:

1. Create your service file:

sudo nano /etc/systemd/system/weather-app.service
Enter fullscreen mode Exit fullscreen mode

2. Add this content:

[Unit]
Description=Weather Forecast Application
After=network.target

[Service]
User=weather-user
WorkingDirectory=/home/weather-user/weather-app
ExecStart=/usr/bin/node server.js
Restart=always
RestartSec=10
Environment=PORT=3000
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target
Enter fullscreen mode Exit fullscreen mode

3. Enable and start the service:

sudo systemctl daemon-reload
sudo systemctl enable weather-app
sudo systemctl start weather-app
Enter fullscreen mode Exit fullscreen mode

4. Check if it's running:

systemctl status weather-app
Enter fullscreen mode Exit fullscreen mode

5. Create a handy shortcut to the logs with a symbolic link:

ln -s /var/log/journal /home/weather-user/Desktop/service-logs
Enter fullscreen mode Exit fullscreen mode

Now your weather app:

  • Starts automatically when your computer boots
  • Restarts if it crashes
  • Runs in the background 24/7
  • Can be easily managed with systemctl commands

Conclusion: Why Services Make Your Life Easier ๐Ÿ’ช

Using systemd services for your Node.js applications is like having a responsible boss (systemd) making sure your workers (services) are always doing their jobs correctly!

Benefits you now enjoy:

  • No more manually keeping your apps running
  • Automatic restart if something crashes
  • Apps start automatically after reboots
  • Simple, consistent commands for management
  • Centralized logging

Remember the master (systemd) and worker (service) relationship, and you'll always have a clear mental model of how Linux services work!

Happy coding! ๐Ÿงโœจ

Top comments (0)