Installation Options

In this post, I’m going to cover 2 methods for installing and configuring Rundeck: Docker installation, and Local installation.

During the process of my initial Docker installation, I was able to get Rundeck in a “working” state, (functioning projects/jobs/commands/nodes, etc.), at least until I wanted to use the Ansible plugin. Rundeck with Ansible integration requires Ansible to be installed on the same “server”, so if we have Rundeck in a container, we would need Ansible to be installed within that container. I couldn’t figure out how to do this, and it seemed rather pointless as it’s not very well documented, so I ended up with the Local server installation method, using a Postgres container as my DB.

Method 1 - Docker Installation

Docker-Compose Setup:

- ${DOCKERCONFDIR}/rundeck/postgres/data:/var/lib/postgresql/data

My Docker-Compose Example:

rundeck:
    image: rundeck/rundeck:4.3.0
    container_name: rundeck
    links:
      - postgres
    environment:
        RUNDECK_DATABASE_DRIVER: org.postgresql.Driver
        RUNDECK_DATABASE_URL: jdbc:postgresql://postgres/rundeck
        RUNDECK_DATABASE_USERNAME: omelsherif
        RUNDECK_DATABASE_PASSWORD: ${DB_PASS}
        RUNDECK_GRAILS_URL: http://192.168.1.20:4440
    volumes:
      - ${RUNDECK_LICENSE_FILE:-/dev/null}:/home/rundeck/etc/rundeckpro-license.key
      - ${DOCKERCONFDIR}/rundeck/server/resources.yaml:/home/rundeck/server/data/resources.yaml
    ports:
      - 4440:4440
    restart: always
  
  postgres:
    image: postgres
    container_name: postgres
    expose:
      - 5432
    environment:
      - POSTGRES_DB=rundeck
      - POSTGRES_USER=omelsherif
      - POSTGRES_PASSWORD=${DB_PASS}
    volumes:
      - ${DOCKERCONFDIR}/rundeck/postgres/data:/var/lib/postgresql/data
    restart: always

Things I changed from the official examples (linked above):

  • You may want to add “http://” in front of your RUNDECK_GRAILS_URL if you’re just accessing it from localhost or from an IP without SSL, otherwise you may run into the error described in this GitHub issue like I did

  • If accessing Rundeck from outside its VM/server, you’ll want to change the RUNDECK_GRAILS_URL value from “localhost” to the IP of your server

  • It’s a good idea to use a .env variable for your DB password so it’s not visible in your compose file

  • The examples show Docker volumes created by Docker, rather than bind volumes on disk; I switched to disk since that’s what I normally use

Run docker-compose up -d and Rundeck should be available at the URL you defined.

Method 2 - Local Installation

You can follow the Rundeck documentation for some simple Linux installation instructions on installing Rundeck itself.

Choosing a database

Rundeck supports several database options. I decided to use Postgres; I don’t have a particular reason other than “it’s what the cool kids use.” That is to say people complain a lot about MySQL, MariaDB seems to be more favorable than that, and Postgres the most favorable. Maybe one day I’ll understand why. In any case, you can then choose to set up your database using either a locally installed instance, or a container. I decided to go with a container as I like to keep things segregated when possible.

Postgres - Docker Container

I used the official Postgres container during my install. Here is my Docker-Compose snippet:

postgres:
    image: postgres
    container_name: postgres
    environment:
      - POSTGRES_DB=rundeck
      - POSTGRES_USER=rundeck
      - POSTGRES_PASSWORD=${DB_PASS}
    volumes:
      - ${DOCKERCONFDIR}/postgres/rundeck:/var/lib/postgresql/data
    ports:
      - 5432:5432
    restart: always

Once the container is up and running, you can connect to it from Rundeck by modifying the configuration file located at /etc/rundeck/rundeck-config.properties. You’ll want to reference the Rundeck/Postgres documentation, but mine currently looks like this:

grails.serverURL=http://192.168.1.20:4440
dataSource.driverClassName = org.postgresql.Driver
dataSource.url = jdbc:postgresql://192.168.1.20/rundeck
dataSource.username = rundeck
dataSource.password = DB_PASS
dataSource.dbCreate = update

In the 3rd line, replace the IP address with either the hostname or IP of the server hosting your Postgres DB. Since I’m using a container, and have port 5432 in the container mapped to port 5432 on my host, I can either use “localhost”, the loopback address, or the IP of my server to make the connection. Once you’ve made the necessary changes, run sudo service rundeckd restart again to restart Rundeck with the new configuration.

NOTE: Check out this guide for some good examples of how to connect to your Postgres server once it’s up to confirm it’s reachable and working.

Postgres - Local DB Install

There are some good instructions for installing a local Postgres DB instance here. Once again, you can combine that with the Postgres Rundeck documentation to connect Rundeck to the database. I often piece together what I need from multiple sources these days. I haven’t followed the local DB installation process to completion, but it should be relatively straightforward.

Logging In

Once Rundeck is up and running, you can reach the login interface. If you haven’t change the default credentials, they will be admin/admin.

Changing default credentials - Docker

From the documentation:

“The default setup utilizes the /home/rundeck/server/config/realm.properties file. Mount or otherwise replace this file to manage further users through this method.”

So basically you’ll want to create a file named realm.properties and mount it with a bind volume, so it remains persistent, similar to how we did the resources.yaml file above.

Changing default credentials - Local

  • nano /etc/rundeck/realm.properties (or use your editor of choice)
  • Find the line admin:admin,user,admin,architect,deploy,build
  • Change to admin:YourNewPassword,user,admin,architect,deploy,build

The default realm.properties file (with changed password) looks something like this:

#
# This file defines users passwords and roles for a HashUserRealm
#
# The format is
#  <username>: <password>[,<rolename> ...]
#
# Passwords may be clear text, obfuscated or checksummed.  The class
# org.mortbay.util.Password should be used to generate obfuscated
# passwords or password checksums
#
# If DIGEST Authentication is used, the password must be in a recoverable
# format, either plain text or OBF:.
#
#jetty: MD5:164c88b302622e17050af52c89945d44,user
#admin: CRYPT:ad1ks..kc.1Ug,server-administrator,content-administrator,admin
#other: OBF:1xmk1w261u9r1w1c1xmq
#plain: plain
#user: password
# This entry is for digest auth.  The credential is a MD5 hash of username:realmname:password
#digest: MD5:6e120743ad67abfbc385bc2bb754e297

#
# This sets the default user accounts for the Rundeck app
#
admin:YourNewPassword,user,admin,architect,deploy,build

#
# example users matching the example aclpolicy template roles
#
#job-runner:admin,user,job_runner
#job-writer:admin,user,job_writer
#job-reader:admin,user,job_reader
#job-viewer:admin,user,job_viewer

Projects

Project creation documentation

SSH Node Execution settings

SSH keygen instructions

Rundeck only accepts keys generated with RSA, use ssh-keygen -t rsa -b 4096 -m PEM

Nodes

Setting up Nodes/SSH

The resources.yaml file just needs to be within a directory that the Rundeck container/user can reach. If using Docker, you can browse the container files in VS Code with the Docker plugin to see possible locations, and then use a Docker bind volume to mount your resources file so it remains persistent, and point to it in the configuration. Example bind mount:

${DOCKERCONFDIR}/rundeck/server/resources.yaml:/home/rundeck/server/data/resources.yaml

You can also use the URL option and point it to the URL of a file on a GitHub repo.

Sample resources.yaml block:

remote-node: #treat this as the displayname
  description: Remote SSH server node
  hostname: node1 #IP address or DNS name
  nodename: node1
  osArch: amd64
  osFamily: unix
  osName: Linux
  osVersion: 5.11.0-7612-generic
  tags: 'node1'
  username: agent #ssh username (omelsherif in my case)
  ssh-key-storage-path: keys/id_rsa #path to ssh key in key storage
  ssh-key-passphrase-storage-path: keys/id_rsa-pass #use if your key has a passphrase
  sudo-password-storage-path: keys/sudo-pass #use if your jobs need sudo

Once you have a remote node configured, you can verify connectivity with a simple command.

Commands & Jobs

You can review the Rundeck documentation for examples/setup of Commands and Jobs.

Configuring SSL

So you’ve got everything up and running, you’ve created a project, added some nodes, ran some commands, and set up a few jobs. Everything seems to be working, but now you want to make things a touch more secure, maybe use a nice domain/subdomain to access Rundeck from.

So let’s configure Rundeck to use SSL! What I’m going to cover here is simply what I did, and what worked for me. I am currently using the SWAG container to handle my certificates and reverse-proxy (Nginx), you can refer to the above link for setup instructions if you’re interested. 

I used a couple sources to assist in getting things working:

These blog posts mostly match up in terms of the configuration, but there were some slight differences. I’m now going to explain what worked for me.

> Nginx

Nginx conf file:

## Version 2021/05/18
# make sure that your dns has a cname set for <container_name> and that your <container_name> container is not using a base url

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name rundeck.walnuthomelab.com; # Replace with your subdomain

    include /config/nginx/ssl.conf;

    client_max_body_size 0;

    location / {
        #add_header          Front-End-Https on;
        proxy_set_header    Host $host;
        proxy_set_header    X-Real-IP $remote_addr;
        proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Proto $scheme;

        proxy_pass          http://192.168.1.20:4440;
        proxy_read_timeout  90;

        proxy_redirect      http://192.168.1.20:4440 https://rundeck.walnuthomelab.com;
        }
}


server {
    listen 80;
    server_name rundeck.walnuthomelab.com;
    return 301 https://$host$request_uri;
}

As you can see from the comment near the top, replace all instances of my domain name with your own. You will also notice the line that says include /config/nginx/ssl.conf; which is an additional file that SWAG generates for the SSL stuff. For the sake of readability, I’ll post the contents here as well:

ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
ssl_session_tickets off;

# intermediate configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;

# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;


### Linuxserver.io Defaults

# Certificates
ssl_certificate /config/keys/letsencrypt/fullchain.pem;
ssl_certificate_key /config/keys/letsencrypt/privkey.pem;
# verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /config/keys/letsencrypt/fullchain.pem;

# Diffie-Hellman Parameters
ssl_dhparam /config/nginx/dhparams.pem;

# Enable TLS 1.3 early data
ssl_early_data on;

If you’re not using SWAG, you can simply refer to the SSL config of the blog posts I linked above. If for some reason those posts have gone missing, using my SSL config *should* work as long as you point it to the correct certificate files. It is all just Nginx after all.

> Rundeck Config

Open /etc/rundeck/framework.properties and make the following modifications:

nano /etc/rundeck/framework.properties
# ----------------------------------------------------------------
# Rundeck server connection information
# ----------------------------------------------------------------

framework.server.name = rundeck.walnuthomelab.com
framework.server.hostname = rundeck.walnuthomelab.com
framework.server.port = 4440
framework.server.url = https://rundeck.walnuthomelab.com

Replace the domains with your own where applicable.

Next, open /etc/rundeck/rundeck-config.properties and make the following modifications:

nano /etc/rundeck/rundeck-config.properties
# change hostname here
grails.serverURL=https://rundeck.walnuthomelab.com

Next, refer to the Rundeck documentation for some further instructions instructions on how to ensure SSL is being listened for.

Finally, restart both Rundeck, and whatever form of Nginx you’re using:

/etc/init.d/rundeckd restart
#If using local Nginx
Systemctl restart nginx
#If using Docker/Swag
docker restart nginx
#or
docker restart swag

Make sure to double check your Nginx logs to verify that you have everything configured correctly and that there are no errors, then visit your subdomain to see if everything works!

Wrap Up

There’s a whole lot more to Rundeck than I’ve explained in this post. I’m still getting the hang of things, especially Ansible integration. But I hope that if anyone is having issues with getting the damn thing running in the first place, they can glean some useful information from this blog post.