Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Apeuriox/lazybot-renewal/llms.txt

Use this file to discover all available pages before exploring further.

Running Lazybot under systemd is the recommended approach for any Linux production deployment. systemd handles automatic restarts on failure, integrates with journalctl for log management, ensures the service starts only after the network and database are ready, and isolates the process under a dedicated non-root user. This page covers the service unit file, the step-by-step setup procedure, log inspection commands, and an overview of the automated CI/CD workflow provided in the repository.

Service Unit File

The repository ships a ready-to-use unit file at scripts/lazybot.service. Copy its content directly or adapt it for your environment:
[Unit]
Description=Lazybot osu! Bot
After=network-online.target mysql.service
Wants=network-online.target

[Service]
Type=simple
User=lazybot
WorkingDirectory=/opt/lazybot
ExecStart=/usr/bin/java --enable-preview --enable-native-access=ALL-UNNAMED -jar /opt/lazybot/lazybot.jar
ExecStop=/bin/kill -SIGTERM $MAINPID
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
SyslogIdentifier=lazybot

Environment=LAZYBOT_DIR=/home/lazybot/work-dir
Environment=ROSU_LIB_PATH=/home/lazybot/rosu

[Install]
WantedBy=multi-user.target

Directive Reference

DirectiveValuePurpose
Afternetwork-online.target mysql.serviceEnsures the network stack and MySQL are fully up before Lazybot starts. Without this, the database connection pool fails to initialise on boot.
Wantsnetwork-online.targetDeclares a soft dependency on the network target — the unit will start even if network-online.target is unavailable, but it prefers to wait for it.
UserlazybotRuns the process as a dedicated non-root system user, limiting the blast radius of any security issue.
WorkingDirectory/opt/lazybotSets the working directory for the process. Place application.yaml here so Spring Boot discovers it automatically.
ExecStart/usr/bin/java --enable-preview --enable-native-access=ALL-UNNAMED -jar /opt/lazybot/lazybot.jarThe exact Java invocation. Both --enable-preview and --enable-native-access=ALL-UNNAMED are required for JNI library loading and Java 21 preview features.
ExecStop/bin/kill -SIGTERM $MAINPIDSends a graceful SIGTERM to allow Spring Boot to complete its shutdown hooks before the process exits.
Restarton-failureAutomatically restarts Lazybot if it exits with a non-zero status code or is killed by a signal.
RestartSec10Waits 10 seconds between restart attempts to avoid rapid restart loops.
StandardOutput / StandardErrorjournalPipes both stdout and stderr into the systemd journal, making logs available via journalctl.
SyslogIdentifierlazybotTags all journal entries with lazybot, enabling filtered log views with -u lazybot or -t lazybot.
Environment=LAZYBOT_DIR/home/lazybot/work-dirWorking directory for Lazybot cache files. Avatars, map backgrounds, and extracted static assets are written here.
Environment=ROSU_LIB_PATH/home/lazybot/rosuDirectory containing the Rosu native library (.so). Lazybot’s JNI binding reads this path at startup.
WantedBymulti-user.targetEnables the service to start automatically in the standard multi-user runlevel.

Installation Steps

1

Create the lazybot System User

Create a dedicated non-interactive system account to run the service. Using a locked shell (/bin/false) prevents anyone from logging in as this user:
sudo useradd -r -s /bin/false lazybot
Also create the working-directory paths referenced in the unit file:
sudo mkdir -p /opt/lazybot /home/lazybot/work-dir /home/lazybot/rosu
sudo chown -R lazybot:lazybot /opt/lazybot /home/lazybot
2

Copy the JAR to /opt/lazybot/

Copy the built artifact from your build machine (or CI pipeline) to the deployment directory:
sudo cp target/lazybot-1.2.0.jar /opt/lazybot/
sudo chown lazybot:lazybot /opt/lazybot/lazybot-1.2.0.jar
3

Create the lazybot.jar Symlink

The service unit references /opt/lazybot/lazybot.jar. Create a symbolic link pointing at the versioned JAR. Using a symlink makes zero-downtime upgrades straightforward — update the symlink, then restart the service.
sudo ln -sf /opt/lazybot/lazybot-1.2.0.jar /opt/lazybot/lazybot.jar
4

Place application.yaml in the Working Directory

Spring Boot automatically picks up an application.yaml located in the working directory of the process. Because the unit file sets WorkingDirectory=/opt/lazybot, place your configured file there:
sudo cp /path/to/your/application.yaml /opt/lazybot/application.yaml
sudo chown lazybot:lazybot /opt/lazybot/application.yaml
sudo chmod 600 /opt/lazybot/application.yaml
chmod 600 restricts read access to the lazybot user only, protecting your embedded secrets.
5

Install the Service File

Copy the unit file from the repository into the systemd system directory:
sudo cp scripts/lazybot.service /etc/systemd/system/lazybot.service
6

Reload systemd and Enable the Service

Tell systemd to re-read its unit files, then enable Lazybot to start at boot and start it immediately:
sudo systemctl daemon-reload
sudo systemctl enable --now lazybot

Managing the Service

Check service status:
sudo systemctl status lazybot
Example output when healthy:
● lazybot.service - Lazybot osu! Bot
     Loaded: loaded (/etc/systemd/system/lazybot.service; enabled; preset: enabled)
     Active: active (running) since Mon 2025-01-20 10:00:00 UTC; 2h 15min ago
   Main PID: 12345 (java)
      Tasks: 42 (limit: 4915)
     Memory: 512.0M
        CPU: 1min 23.456s
     CGroup: /system.slice/lazybot.service
             └─12345 /usr/bin/java --enable-preview --enable-native-access=ALL-UNNAMED -jar /opt/lazybot/lazybot.jar
Restart the service (e.g. after an upgrade):
sudo systemctl restart lazybot
Stop the service:
sudo systemctl stop lazybot

Viewing Logs

All Lazybot output is forwarded to the systemd journal. Use journalctl to inspect it: Follow logs in real time (Ctrl+C to exit):
sudo journalctl -u lazybot -f
View the last 200 lines:
sudo journalctl -u lazybot -n 200
View logs since the last boot:
sudo journalctl -u lazybot -b
Filter by time range:
sudo journalctl -u lazybot --since "2025-01-20 10:00:00" --until "2025-01-20 11:00:00"

CI/CD Deployment with GitHub Actions

The repository includes a GitHub Actions workflow at .github/workflows/deploy.yml that automates building and deploying Lazybot to your server on every push to the dev branch (or on manual trigger via workflow_dispatch). The workflow performs the following steps:
  1. Checkout the repository source.
  2. Set up Java 21 (Temurin distribution) using actions/setup-java@v4.
  3. Prepare application.yaml by copying the template (application.yaml.template) into place. Secrets are expected to already be present on the server’s application.yaml — the template is used only to satisfy the build.
  4. Build with Maven (mvn clean package -DskipTests) to produce the versioned JAR.
  5. Deploy the JAR via SCP using appleboy/scp-action. The JAR is transferred to /opt/lazybot/ on the remote server. The required secrets are SSH_HOST, SSH_USER, and SSH_PRIVATE_KEY, configured in your repository’s GitHub Actions secrets.
  6. Update the symlink and restart via SSH using appleboy/ssh-action. The remote script:
    • Finds the most recently built lazybot-*.jar in /opt/lazybot/.
    • Updates the lazybot.jar symlink to point at the new JAR.
    • Runs sudo systemctl restart lazybot and prints the service status.
# Remote script executed after SCP transfer
LATEST_JAR=$(ls -t /opt/lazybot/lazybot-*.jar 2>/dev/null | head -1)
if [ -n "$LATEST_JAR" ]; then
  ln -sf "$LATEST_JAR" /opt/lazybot/lazybot.jar
fi
sudo systemctl restart lazybot
sudo systemctl status lazybot --no-pager
Because WorkingDirectory in the service file is /opt/lazybot, Spring Boot will automatically load application.yaml from that directory at startup. Keep your production application.yaml there and ensure the lazybot user has read access to it. The CI/CD workflow does not redeploy application.yaml — you manage it separately on the server to keep secrets out of the pipeline.

Build docs developers (and LLMs) love