Skip to content

Container - PostgreSQL

PostgreSQL is a powerful, open-source relational database system known for reliability, feature robustness, and performance. Running PostgreSQL as a Container on RouterOS enables local data storage for applications, providing a complete SQL database engine without requiring dedicated hardware.

PostgreSQL supports advanced features including ACID transactions, stored procedures, triggers, views, foreign keys, and JSON support. When deployed as a Container on MikroTik routers, it serves as a lightweight database solution for edge computing applications, IoT data collection, and small-scale deployments.

PostgreSQL Containers require significant storage I/O performance. Always use external storage (USB, SATA, NVMe) with good sequential read/write speeds. Running PostgreSQL on router SPI flash storage will result in severe performance degradation and potential data corruption.

Store application data locally without relying on cloud services. This is ideal for:

  • IoT data collection and logging
  • Local application state persistence
  • Configuration storage for containerized services

Create a local database environment for development and testing without dedicated hardware:

  • Prototype applications before production deployment
  • Test database-backed applications
  • Experiment with SQL queries and PostgreSQL features

Deploy databases at the network edge for reduced latency and offline capability:

  • Local caching of frequently accessed data
  • Branch office database requirements
  • Standalone network operations

Before deploying PostgreSQL, ensure you have a Container network configured with a virtual ethernet (veth) interface:

/interface/veth/print
Flags: X - disabled, A - active, * - default
# NAME MTU ADDRESS GATEWAY
0 veth1 1500 172.17.0.1/24 172.17.0.1

If you need to create a new Container network, refer to the Container networking documentation for detailed instructions.

PostgreSQL requires adequate storage and I/O performance:

ResourceMinimumRecommended
Storage500MB2GB+
I/O Performance100 IOPS1000+ IOPS
RAM256MB512MB+

Never run PostgreSQL on SPI flash storage. Use only external USB, SATA, or NVMe storage with sufficient performance.

PostgreSQL Container uses environment variables for initial configuration:

VariableDescriptionDefault
POSTGRES_PASSWORDPassword for postgres superuserrequired
POSTGRES_USERCreate additional superuserpostgres
POSTGRES_DBDefault database namepostgres

Create directories on your external storage for PostgreSQL data and configuration:

/file add type=directory name=disk1/postgres/data
/file add type=directory name=disk1/postgres/config

Create mount points to persist PostgreSQL data and configuration:

/container/mounts/add name=postgres_data src=disk1/postgres/data dst=/var/lib/postgresql/data
/container/mounts/add name=postgres_config src=disk1/postgres/config dst=/etc/postgresql

The data mount ensures database files persist across Container restarts. The config mount allows custom PostgreSQL configuration.

Add the PostgreSQL Container using the official PostgreSQL image:

/container/add remote-image=postgres:16-alpine interface=veth1 root-dir=disk1/images/postgres mounts=postgres_data,postgres_config envs=POSTGRES_PASSWORD=YourSecurePassword123 name=postgres start-on-boot=yes

This command:

  • Uses the alpine-based PostgreSQL 16 image (smaller footprint)
  • Connects the Container to the specified virtual interface
  • Sets the root directory for Container data
  • Mounts data and configuration directories
  • Sets the postgres password environment variable
  • Enables auto-start on router boot
/container start [find where name=postgres]

Verify the Container is running:

/container/print
Flags: X - disabled, R - running
0 R name="postgres" id="abc123..." interface=veth1 ...

Check the logs for PostgreSQL initialization:

/log print follow

You should see messages indicating PostgreSQL is ready to accept connections:

2024-01-15 10:30:00.123 UTC [1] LOG: database system is ready to accept connections

RouterOS does not include a native PostgreSQL client. Use a Container with psql installed or connect from a remote client machine.

Allow remote connections by configuring PostgreSQL authentication and RouterOS firewall:

Create a custom PostgreSQL configuration to allow remote connections:

  1. Mount a custom configuration directory
  2. Edit pg_hba.conf to allow password authentication:
# TYPE DATABASE USER ADDRESS METHOD
host all all 0.0.0.0/0 md5
host all all ::/0 md5
  1. Edit postgresql.conf to listen on all addresses:
listen_addresses = '*'

Allow PostgreSQL port (5432) through the firewall:

/ip/firewall/filter/add chain=input protocol=tcp dst-port=5432 in-interface=veth1 action=accept

Application connection string examples:

postgresql://postgres:YourSecurePassword123@172.17.0.2:5432/mydb

Replace 172.17.0.2 with your PostgreSQL Container’s IP address (check via /interface/veth/print).

Key postgresql.conf settings for Container deployments:

SettingDescriptionRecommended Value
shared_buffersMemory for caching data128MB (adjust based on available RAM)
max_connectionsMaximum client connections100
work_memMemory for sorting operations4MB
maintenance_work_memMemory for maintenance operations64MB
fsyncForce writes to diskon (never disable)
wal_levelWrite-ahead log levelreplica

Create a custom PostgreSQL configuration file:

/container/mounts/add name=postgres_config src=disk1/postgres/config dst=/etc/postgresql/conf.d

Create postgresql.conf in the mounted config directory:

# Memory settings
shared_buffers = 128MB
work_mem = 4MB
maintenance_work_mem = 64MB
# Connection settings
max_connections = 100
listen_addresses = '*'
# Write-ahead log
wal_level = replica
max_wal_senders = 3
# Logging
log_destination = 'stderr'
logging_collector = on
log_directory = '/var/log/postgresql'

Connect to PostgreSQL and create databases:

Terminal window
psql -h 172.17.0.2 -U postgres -c "CREATE DATABASE myapp;"
psql -h 172.17.0.2 -U postgres -c "CREATE USER myuser WITH PASSWORD 'userpassword';"
psql -h 172.17.0.2 -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE myapp TO myuser;"
CREATE TABLE devices (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
ip_address INET,
last_seen TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO devices (name, ip_address) VALUES ('router1', '192.168.1.1');
SELECT * FROM devices;
Terminal window
pg_dump -h 172.17.0.2 -U postgres mydb > backup.sql
Terminal window
psql -h 172.17.0.2 -U postgres mydb < backup.sql

pgAdmin is a web-based administration tool for PostgreSQL. Running pgAdmin alongside PostgreSQL provides a graphical interface for database management.

/container/mounts/add name=pgadmin_data src=disk1/pgadmin/data dst=/var/lib/pgadmin
/container/mounts/add name=pgadmin_config src=disk1/pgadmin/config dst=/var/lib/pgadmin/storage
/container/mounts/add name=pgadmin_logs src=disk1/pgadmin/logs dst=/var/log/pgadmin
/container/add remote-image=dpage/pgadmin4:latest interface=veth1 root-dir=disk1/images/pgadmin mounts=pgadmin_data,pgadmin_config,pgadmin_logs envs[email protected],PGADMIN_DEFAULT_PASSWORD=AdminPassword123 name=pgadmin start-on-boot=yes

pgAdmin runs on port 80 inside the Container. Access it through the router:

  1. Determine pgAdmin Container IP: /interface/veth/print
  2. Open browser to http://<router-ip>/pgadmin4/
  3. Login with credentials set in environment variables

In pgAdmin:

  1. Right-click “Servers” → “Create” → “Server”
  2. Name: PostgreSQL
  3. Connection tab:
    • Host name/address: 172.17.0.2 (PostgreSQL Container IP)
    • Port: 5432
    • Username: postgres
    • Password: YourSecurePassword123
  1. Verify sufficient storage space: /system/resource/print
  2. Check storage I/O performance
  3. Verify mount point directories exist
  4. Check logs for specific errors: /log print
/container/print detail
  1. Verify Container is running: /container/print
  2. Check Container IP address: /interface/veth/print
  3. Test connectivity: /tool ping 172.17.0.2
  4. Verify firewall allows connections
/ip/firewall/filter/print
/interface/veth/print detail
  1. Check storage performance (avoid SPI flash)
  2. Review PostgreSQL memory settings
  3. Monitor system resources: /system resource/print
  4. Consider dedicated storage device for database
/system/resource/print
  1. Always use external storage with good I/O
  2. Never stop Container without graceful shutdown
  3. Regular backups are essential
  4. Check filesystem integrity

If you forget the postgres password:

  1. Stop the Container
  2. Edit the Container to remove envs
  3. Start Container with new password environment variable
  4. Connect and reset password:
ALTER USER postgres WITH PASSWORD 'newpassword';
  • Use firewall rules to limit PostgreSQL access
  • Consider VPN for remote database access
  • Never expose PostgreSQL directly to the internet
  • Use strong passwords
  • Consider certificate-based authentication for production
  • Limit superuser access
  • Regular backups to external location
  • Encrypt sensitive data at application layer
  • Monitor access logs