Akaunting

How to Install Akaunting on a VPS using Docker

Running a business means tracking money, and tracking money usually means handing your books over to a subscription service that charges per user, per month, forever. Akaunting offers a different deal. It’s free, open-source accounting software that handles invoicing, expenses, bills, and reporting, and you can run the whole thing on your own server. No seat limits. No locked features behind a premium tier you didn’t ask for.

This guide takes you from a fresh Ubuntu VPS to a working Akaunting install using Docker Compose. You’ll get a clean container setup, a reverse proxy with HTTPS, and a backup routine that keeps your financial data safe. Let’s dig in.

What Is Akaunting?

Akaunting is a full-featured accounting application built on the Laravel PHP framework. Small businesses, freelancers, and accountants use it to send invoices, record expenses, manage customers and vendors, and pull financial reports. It supports multiple companies, multiple currencies, and multiple users, all from a clean web dashboard.

The hosted version exists, but self-hosting is where it gets interesting. Your client data, your invoices, and your transaction history all stay on hardware you control. There’s an app store for extra modules too, though the core covers what most businesses need on day one.

Why Docker? Akaunting needs PHP, a stack of extensions, Composer, and a database wired together just so. Docker bundles all of that into containers, which means you skip the dependency juggling and get a setup that behaves the same way every time. Updates get easier too.

Prerequisites

Before touching the terminal, make sure you’ve got the following ready:

RequirementMinimumRecommended
OSUbuntu 20.04Ubuntu 22.04 LTS
RAM1 GB2 GB or more
CPU1 vCPU2 vCPUs
Storage10 GB20 GB SSD
SoftwareDocker + ComposeLatest stable Docker
AccessRoot or sudo user 
DomainOptionalStrongly recommended for HTTPS

A domain name pointed at your server makes the HTTPS step much smoother. If you don’t have one yet, you can still reach Akaunting by IP address, but you’ll want a domain before going live with real data.

Step 1: Connect to Your VPS

Open your terminal and SSH into the server. Swap in your real username and IP address:

ssh your_user@your_server_ip

Run a full system update first. It’s a thirty-second habit that heads off a surprising number of installation headaches.

sudo apt update && sudo apt upgrade -y

Step 2: Install Docker and Docker Compose

Akaunting runs inside Docker containers, so Docker comes first. Grab the official convenience script, which installs the latest stable Docker Engine along with the Compose plugin:

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

Add your user to the docker group so you can run commands without typing sudo every time:

sudo usermod -aG docker $USER

Log out and back in for that group change to take effect. Then confirm both Docker and Compose are working:

docker --version
docker compose version

Two version numbers means you’re good to keep moving.

Step 3: Set Up the Project Directory

Keeping everything in one folder makes the install tidy and the backups simple later. Create a directory and move into it:

mkdir -p /opt/akaunting
cd /opt/akaunting

Now create an environment file to hold your passwords and settings. Storing secrets here keeps them out of the main Compose file, which is good hygiene:

nano .env

Paste in the following, then change every password and the domain to match your own setup:

# Database settings
DB_ROOT_PASSWORD=change_this_root_password
DB_NAME=akaunting
DB_USER=akaunting
DB_PASSWORD=change_this_db_password

# Akaunting admin account
[email protected]
ADMIN_PASSWORD=change_this_admin_password

# Company and app
COMPANY_NAME=Your Company Name
APP_URL=https://accounting.yourdomain.com
LOCALE=en-GB

Save and exit with Ctrl + X, then Y, then Enter.

Important: Use long, unique passwords for all three values. This system holds your financial records and customer details, so treat these credentials with the same care you’d give a bank login.

Step 4: Create the Docker Compose File

This file defines two containers: Akaunting itself and a MariaDB database for it to talk to. Create it now:

nano docker-compose.yml

Paste in the configuration below. The ${VAR} references automatically pull values from the .env file you just created:

services:
  akaunting:
    image: akaunting/akaunting:latest
    container_name: akaunting
    restart: unless-stopped
    depends_on:
      - mariadb
    ports:
      - "8080:80"
    environment:
      AKAUNTING_SETUP: "true"
      DB_HOST: mariadb
      DB_PORT: 3306
      DB_NAME: ${DB_NAME}
      DB_USERNAME: ${DB_USER}
      DB_PASSWORD: ${DB_PASSWORD}
      DB_PREFIX: aka_
      APP_URL: ${APP_URL}
      LOCALE: ${LOCALE}
      COMPANY_NAME: ${COMPANY_NAME}
      COMPANY_EMAIL: ${ADMIN_EMAIL}
      ADMIN_EMAIL: ${ADMIN_EMAIL}
      ADMIN_PASSWORD: ${ADMIN_PASSWORD}
    volumes:
      - akaunting_data:/var/www/html

  mariadb:
    image: mariadb:11
    container_name: akaunting_db
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
      MYSQL_DATABASE: ${DB_NAME}
      MYSQL_USER: ${DB_USER}
      MYSQL_PASSWORD: ${DB_PASSWORD}
    volumes:
      - akaunting_db:/var/lib/mysql

volumes:
  akaunting_data:
  akaunting_db:

A few things worth knowing about this file. The akaunting_data and akaunting_db volumes persist your files and database outside the containers, so your data survives restarts and updates. The 8080:80 mapping exposes the app on port 8080 of your server, which the reverse proxy will sit in front of shortly. The AKAUNTING_SETUP: "true" line tells the container to run its first-time installer automatically.

Heads up: Akaunting’s Docker image occasionally renames environment variables between major releases. If a value here doesn’t take, cross-check the current names against the official Akaunting Docker repository.

Step 5: Launch the Containers

With both files in place, bring the stack to life:

docker compose up -d

The -d flag runs everything in the background. Docker downloads the images, starts MariaDB, then starts Akaunting, which runs its installer and connects to the database. The first launch takes a couple of minutes since the installer has to build the database tables.

Watch the logs to follow along:

docker compose logs -f akaunting

Once the logs settle and the installer reports success, press Ctrl + C to stop watching. The containers keep running in the background.

Step 6: Disable the Installer

The setup flag did its job, and leaving it on could re-trigger the installer on a future restart. Open your Compose file again:

nano docker-compose.yml

Change the setup line from "true" to "false":

      AKAUNTING_SETUP: "false"

Save, then apply the change by recreating the container:

docker compose up -d

Your data stays untouched because it lives in the named volumes, not the container.

Step 7: Set Up a Reverse Proxy

Right now Akaunting answers on port 8080. You want it on standard web ports with a proper domain and, soon, HTTPS. A reverse proxy handles that. Pick whichever web server you already know or prefer. Both work equally well here.

Option A: Nginx

Install Nginx:

sudo apt install -y nginx
sudo systemctl enable nginx

Create a server block. Replace accounting.yourdomain.com with your real domain throughout:

sudo nano /etc/nginx/sites-available/akaunting
server {
    listen 80;
    server_name accounting.yourdomain.com;

    # Allow large invoice and document uploads
    client_max_body_size 50M;

    location / {
        proxy_pass http://127.0.0.1:8080;
        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;
    }
}

Enable the site, test the config, and reload:

sudo ln -s /etc/nginx/sites-available/akaunting /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Option B: Apache

Install Apache and enable the proxy modules it needs:

sudo apt install -y apache2
sudo a2enmod proxy proxy_http headers
sudo systemctl enable apache2

Create a virtual host file:

sudo nano /etc/apache2/sites-available/akaunting.conf
<VirtualHost *:80>
    ServerName accounting.yourdomain.com

    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:8080/
    ProxyPassReverse / http://127.0.0.1:8080/

    RequestHeader set X-Forwarded-Proto "http"

    LimitRequestBody 52428800
</VirtualHost>

Enable the site and reload Apache:

sudo a2ensite akaunting.conf
sudo apache2ctl configtest
sudo systemctl reload apache2

Run Nginx or Apache, never both at once. They’ll fight over ports 80 and 443 if you do.

Step 8: Enable HTTPS with Let’s Encrypt

An accounting app passing logins and financial data over plain HTTP is asking for trouble. Certbot issues a free, trusted certificate and wires it into your web server automatically.

Make sure your domain’s DNS A record points to your VPS IP first, since Certbot verifies ownership by reaching your server. Then install the matching Certbot plugin.

For Nginx:

sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d accounting.yourdomain.com

For Apache:

sudo apt install -y certbot python3-certbot-apache
sudo certbot --apache -d accounting.yourdomain.com

Certbot asks for an email, confirms the terms, and offers to redirect all HTTP traffic to HTTPS. Accept the redirect. Within a minute your site serves over a secure connection.

Because you’re now serving over HTTPS, update the APP_URL in your .env file to use https:// if it doesn’t already, then recreate the container with docker compose up -d. This keeps Akaunting’s generated links pointing at the secure address.

Certbot renews certificates automatically. Confirm the renewal timer is active:

sudo systemctl status certbot.timer

Step 9: Configure Your Firewall

Close everything except what you actually need. This allows SSH plus web traffic and blocks the rest, including direct access to port 8080:

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

If you chose Apache instead of Nginx, swap that middle line for sudo ufw allow 'Apache Full'. Check the result:

sudo ufw status

Step 10: Log In and Verify

Open https://accounting.yourdomain.com in your browser. You’ll see the Akaunting login screen. Sign in with the admin email and password you set in your .env file.

Once you’re in, you’ll land on the dashboard. Set your company details, currency, and fiscal year, then send a test invoice to confirm everything works end to end.

To check the containers from the server side, run:

docker compose ps

Both services should show a status of running or healthy.

Backing Up Your Data

This step isn’t optional for an accounting system. A corrupted database or a fat-fingered command shouldn’t be able to erase your financial history. Two things need backing up: the database and the application files.

Dump the database to a file with this command. It runs mysqldump inside the database container and saves the output to your project folder:

docker exec akaunting_db sh -c \
  'exec mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" akaunting' \
  > /opt/akaunting/backup-$(date +%F).sql

Back up the uploaded files (logos, invoice attachments, and the like) by archiving the data volume:

docker run --rm \
  -v akaunting_akaunting_data:/data \
  -v /opt/akaunting:/backup \
  alpine tar czf /backup/files-$(date +%F).tar.gz -C /data .

For real peace of mind, drop both commands into a shell script and schedule it with cron to run nightly. Then copy those backups off the server to remote storage, because a backup that lives only on the same machine isn’t really a backup.

Updating Akaunting

Docker makes updates clean. Pull the newest image and recreate the containers:

cd /opt/akaunting
docker compose pull
docker compose up -d

Your named volumes carry the data forward, so nothing gets lost. Run a database backup before any major version jump, just in case the update includes schema changes you’d want to roll back from.

Troubleshooting Common Issues

The page won’t load at all

Check that both containers are actually up:

docker compose ps
docker compose logs akaunting

502 Bad Gateway from the proxy

Your web server can’t reach the container. Confirm Akaunting is listening on port 8080 and that the proxy_pass address matches. A container that’s still starting up can also cause this, so give it a minute after launch.

Database connection errors in the logs

The database password in your .env file doesn’t match what MariaDB initialized with. If you changed it after the first launch, MariaDB kept the original. Either match the old password or wipe the database volume and start fresh with docker compose down -v, which deletes all data.

Styles and links point to the wrong address

Your APP_URL doesn’t match the address you’re actually visiting. Update it in .env to the exact domain and protocol you use, then run docker compose up -d to apply it.

Certbot can’t issue a certificate

DNS probably hasn’t propagated, or the A record points to the wrong IP. Run dig accounting.yourdomain.com to see where it resolves, wait a few minutes, then try again.

What to Do Next

Your books now live on a server you control. A few worthwhile next moves:

  • Add your team: Create user accounts with role-based permissions so staff see only what they should.
  • Explore the app store: Akaunting offers modules for payroll, inventory, custom reports, and payment gateways.
  • Set up recurring invoices: Automate billing for retainer clients and subscriptions.
  • Connect a payment gateway: Let clients pay invoices online and watch transactions reconcile themselves.

Wrapping Up

There’s the whole picture. Docker and Compose running the app and its database, a reverse proxy fronting it, Let’s Encrypt securing the connection, and a backup routine guarding your records. It’s a stable, self-contained stack that updates with two commands and survives reboots without a fuss.

The payoff goes beyond saving on subscription fees. Your financial data sits on your own server, under your own rules, with no third party deciding how long they’ll keep it or what it costs to access. For a system that holds something as sensitive as your books, that kind of control is hard to put a price on.

Now go send that first invoice.