Here is a step-by-step guide to creating a robust systemd service and timer for your ChangeIP update script on a Raspberry Pi.
Step 1: Refine and Place the Script
The original script is designed for interactive use or a simple cron job. We'll make a few small tweaks to make it better for a non-interactive system service. The main changes are:
- Remove the hardcoded credentials.
- Have it read credentials from environment variables.
- Direct its output to standard output (
stdout) sosystemd's journaling system can capture it, which is more efficient than managing a separate log file.
First, create the script file.
sudo nano /usr/local/bin/changeip-update.sh
Now, paste the following modified script into the editor:
#!/bin/bash
# A script to update a ChangeIP.com DDNS record.
# Modified for use with systemd. Credentials are now passed via environment variables.
# Logging is handled by redirecting echo to stdout for journalctl.
# These variables are still useful for the script's internal logic.
IPPATH=/tmp/current_ip
TMPIP=/tmp/new_ip
# --- Configuration (Credentials should be in the environment file) ---
# CIPUSER is read from the environment
# CIPPASS is read from the environment
CIPSET=1 # DDNS SET 1 or 2. Ensure your domains are in this set on ChangeIP.com.
# Get the current public IP address
NEW_IP=$(curl -s 'https://ip.changeip.com' | grep 'IPADDR' | cut -d'=' -f2)
# Exit if we couldn't get the new IP
if [ -z "$NEW_IP" ]; then
echo "Error: Could not retrieve new IP address from changeip.com." >&2
exit 1
fi
echo "$NEW_IP" > "$TMPIP"
# If the old IP file doesn't exist, create it to trigger an initial update.
if [ ! -f "$IPPATH" ]; then
touch "$IPPATH"
fi
# Compare old IP with new IP.
if diff -q "$IPPATH" "$TMPIP" > /dev/null
then
# IPs are the same. No update needed.
echo "IP address has not changed: $NEW_IP. No update performed."
else
# IPs are different. Trigger an update.
echo "IP address has changed. Old: $(cat $IPPATH), New: $NEW_IP. Updating..."
# Perform the update using credentials from the environment.
UPDATE_RESPONSE=$(curl -s "https://nic.changeip.com/nic/update?u=$CIPUSER&p=$CIPPASS&set=$CIPSET")
echo "Update response from ChangeIP: $UPDATE_RESPONSE"
# Store the new IP for the next check.
mv "$TMPIP" "$IPPATH"
fi
exit 0
After pasting the script, make it executable:
sudo chmod +x /usr/local/bin/changeip-update.sh
Step 2: Create a Secure Environment File for Credentials
This file will hold your credentials. systemd will load this file before running the script, keeping the credentials out of the main script and process list.
- Create the environment file:
sudo nano /etc/default/changeip - Add your credentials to this file:
# ChangeIP Credentials CIPUSER="YOUR_EMAIL" CIPPASS="YOUR_PASSWORD"Note: The script is configured for
CIPSET=1. Ensure domains are configured in Set 1 in your ChangeIP.com account settings. - Set strict permissions on the file so only the
rootuser can read it:sudo chmod 600 /etc/default/changeip
Step 3: Create the systemd Service File
The service file tells systemd what to run.
- Create the service unit file:
sudo nano /etc/systemd/system/changeip.service -
Paste the following configuration:
[Unit] Description=ChangeIP Dynamic DNS Update Service After=network.target [Service] Type=oneshot User=root EnvironmentFile=/etc/default/changeip ExecStart=/usr/local/bin/changeip-update.sh [Install] WantedBy=multi-user.targetAfter=network.target: Ensures the network is up before running.Type=oneshot: Indicates that this is a short-running task, not a long-running daemon.EnvironmentFile: This is the key to securely loading your credentials.
Step 4: Create the systemd Timer File
The timer file tells systemd when to run your service, replacing the need for cron.
- Create the timer unit file:
sudo nano /etc/systemd/system/changeip.timer -
Paste the following configuration:
[Unit] Description=Run ChangeIP DDNS update every 5 minutes [Timer] OnBootSec=2min OnUnitActiveSec=5min Unit=changeip.service [Install] WantedBy=timers.targetOnBootSec=2min: Runs the service 2 minutes after the Pi boots up.OnUnitActiveSec=5min: Runs the service every 5 minutes after the last time it was run.Unit=changeip.service: Specifies which service this timer controls.
Step 5: Enable and Start the Timer
Now, you just need to tell systemd to load these new files and enable the timer.
- Reload the
systemddaemon to make it aware of the new files:sudo systemctl daemon-reload - Enable the timer to start automatically on boot:
sudo systemctl enable changeip.timer - Start the timer now:
sudo systemctl start changeip.timer
Step 6: Verify and Monitor the Service
You can now check that everything is working as expected.
- Check the status of the timer to see when it will run next:
systemctl list-timersYou should see
changeip.timerin the list. - View the logs from your service. All the
echostatements from the script are automatically captured by the journal.sudo journalctl -u changeip.service -f- Use
-fto follow the log in real-time. - Press
Ctrl+Cto exit the log view.
- Use
You have now successfully converted the script into a modern, secure, and reliable service on your Raspberry Pi.