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! ๐Ÿงโœจ

Sentry blog image

How I fixed 20 seconds of lag for every user in just 20 minutes.

Our AI agent was running 10-20 seconds slower than it should, impacting both our own developers and our early adopters. See how I used Sentry Profiling to fix it in record time.

Read more

Top comments (0)

The best way to debug slow web pages cover image

The best way to debug slow web pages

Tools like Page Speed Insights and Google Lighthouse are great for providing advice for front end performance issues. But what these tools canโ€™t do, is evaluate performance across your entire stack of distributed services and applications.

Watch video

๐Ÿ‘‹ Kindness is contagious

If you found this post helpful, please leave a โค๏ธ or a friendly comment below!

Okay