Streaming SQL
    Apache 2.0

    Deploy RisingWave on a VPS

    A distributed streaming SQL database with PostgreSQL wire compatibility — incremental materialized views over Kafka, CDC, and S3 sources.

    At a Glance

    ProjectRisingWave 2.x (single-node)
    LicenseApache 2.0
    Recommended PlanRamNode Premium NVMe 8 vCPU / 16 GB
    OSUbuntu 24.04 LTS
    WirePostgreSQL on 4566
    1

    System Prep

    Base packages
    sudo apt update && sudo apt upgrade -y
    sudo apt install -y curl wget gnupg ca-certificates ufw \
      postgresql postgresql-contrib build-essential pkg-config libssl-dev
    2

    MinIO Object Storage

    Install MinIO
    sudo useradd --system --shell /usr/sbin/nologin --home-dir /var/lib/minio --create-home minio-user
    sudo mkdir -p /var/lib/minio/data /etc/minio
    sudo chown -R minio-user:minio-user /var/lib/minio /etc/minio
    
    wget https://dl.min.io/server/minio/release/linux-amd64/minio -O /tmp/minio
    sudo install -m 0755 /tmp/minio /usr/local/bin/minio
    /etc/default/minio
    MINIO_VOLUMES="/var/lib/minio/data"
    MINIO_OPTS="--address 127.0.0.1:9000 --console-address 127.0.0.1:9001"
    MINIO_ROOT_USER="risingwave-admin"
    MINIO_ROOT_PASSWORD="<strong-password-here>"
    /etc/systemd/system/minio.service
    [Unit]
    Description=MinIO
    After=network-online.target
    Wants=network-online.target
    
    [Service]
    Type=notify
    User=minio-user
    Group=minio-user
    EnvironmentFile=/etc/default/minio
    ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES
    Restart=always
    LimitNOFILE=65536
    
    [Install]
    WantedBy=multi-user.target
    Start + create bucket
    sudo systemctl daemon-reload
    sudo systemctl enable --now minio
    
    wget https://dl.min.io/client/mc/release/linux-amd64/mc -O /tmp/mc
    sudo install -m 0755 /tmp/mc /usr/local/bin/mc
    
    mc alias set local http://127.0.0.1:9000 risingwave-admin '<strong-password-here>'
    mc mb local/hummock
    3

    PostgreSQL Metastore

    Create role + DB
    sudo -u postgres psql <<EOF
    CREATE USER risingwave WITH ENCRYPTED PASSWORD '<metastore-password>';
    CREATE DATABASE risingwave_meta OWNER risingwave;
    GRANT ALL PRIVILEGES ON DATABASE risingwave_meta TO risingwave;
    EOF
    4

    Install RisingWave

    Service user + binary
    sudo useradd --system --shell /usr/sbin/nologin --home-dir /var/lib/risingwave --create-home risingwave
    sudo mkdir -p /opt/risingwave /var/log/risingwave /etc/risingwave
    sudo chown -R risingwave:risingwave /var/lib/risingwave /var/log/risingwave /etc/risingwave /opt/risingwave
    
    cd /tmp
    RW_VERSION="2.1.0"
    wget "https://github.com/risingwavelabs/risingwave/releases/download/v${RW_VERSION}/risingwave-v${RW_VERSION}-x86_64-unknown-linux-all-in-one.tar.gz"
    tar -xzf "risingwave-v${RW_VERSION}-x86_64-unknown-linux-all-in-one.tar.gz"
    sudo install -m 0755 risingwave /opt/risingwave/risingwave
    sudo chown -R risingwave:risingwave /opt/risingwave
    /opt/risingwave/risingwave --version
    5

    Configuration

    /etc/risingwave/risingwave.toml
    [server]
    heartbeat_interval_ms = 1000
    
    [meta]
    periodic_compaction_interval_sec = 60
    vacuum_interval_sec = 30
    
    [batch]
    worker_threads_num = 4
    
    [streaming]
    actor_runtime_worker_threads_num = 4
    
    [storage]
    shared_buffer_capacity_mb = 1024
    block_cache_capacity_mb = 1024
    meta_cache_capacity_mb = 512
    /etc/risingwave/risingwave.env
    RW_SQL_ENDPOINT=postgres://risingwave:<metastore-password>@127.0.0.1:5432/risingwave_meta
    RW_BACKEND=sql
    RW_STATE_STORE=hummock+minio://risingwave-admin:<strong-password-here>@127.0.0.1:9000/hummock
    RW_DATA_DIRECTORY=hummock_001
    RW_LISTEN_ADDR=0.0.0.0:5690
    RW_HOST_ADDR=127.0.0.1:5690
    RW_FRONTEND_LISTEN_ADDR=0.0.0.0:4566
    RW_FRONTEND_HOST_ADDR=127.0.0.1:4566
    RW_PROMETHEUS_LISTEN_ADDR=127.0.0.1:1250
    RW_DASHBOARD_LISTEN_ADDR=127.0.0.1:5691
    RW_CONFIG_PATH=/etc/risingwave/risingwave.toml
    Lock the env file
    sudo chmod 0640 /etc/risingwave/risingwave.env
    sudo chown root:risingwave /etc/risingwave/risingwave.env
    6

    systemd + Firewall

    /etc/systemd/system/risingwave.service
    [Unit]
    Description=RisingWave Single Node
    After=network-online.target postgresql.service minio.service
    Wants=network-online.target
    Requires=postgresql.service minio.service
    
    [Service]
    Type=simple
    User=risingwave
    Group=risingwave
    EnvironmentFile=/etc/risingwave/risingwave.env
    ExecStart=/opt/risingwave/risingwave single-node
    Restart=on-failure
    RestartSec=10
    LimitNOFILE=1048576
    
    NoNewPrivileges=true
    PrivateTmp=true
    ProtectSystem=strict
    ProtectHome=true
    ReadWritePaths=/var/lib/risingwave /var/log/risingwave
    
    [Install]
    WantedBy=multi-user.target
    Enable + UFW
    sudo systemctl daemon-reload
    sudo systemctl enable --now risingwave
    
    sudo ufw default deny incoming && sudo ufw default allow outgoing
    sudo ufw allow OpenSSH
    sudo ufw allow from 203.0.113.10 to any port 4566 proto tcp
    sudo ufw enable
    7

    Verify + Create Sources

    Connect via psql
    psql -h <vps-ip> -p 4566 -d dev -U root
    Datagen smoke test
    CREATE SOURCE test_source (
      sequence_int INT,
      timestamp_col TIMESTAMP
    ) WITH (
      connector = 'datagen',
      fields.sequence_int.kind = 'sequence',
      fields.sequence_int.start = '1',
      fields.sequence_int.end = '10000',
      datagen.rows.per.second = '100'
    ) FORMAT PLAIN ENCODE JSON;
    
    CREATE MATERIALIZED VIEW test_count AS
    SELECT count(*) AS total FROM test_source;
    Postgres CDC source
    CREATE SOURCE pg_cdc WITH (
      connector = 'postgres-cdc',
      hostname = 'postgres.internal',
      port = '5432',
      username = 'cdc_user',
      password = '<password>',
      database.name = 'app',
      slot.name = 'risingwave',
      publication.name = 'rw_pub'
    );
    
    CREATE TABLE orders_replica (
      order_id BIGINT PRIMARY KEY,
      customer_id BIGINT,
      amount NUMERIC,
      created_at TIMESTAMP
    ) FROM pg_cdc TABLE 'public.orders';
    8

    Backups + Monitoring

    Nightly backup
    #!/bin/bash
    set -euo pipefail
    TS=$(date +%Y%m%d-%H%M%S)
    DEST="/var/backups/risingwave/${TS}"
    mkdir -p "${DEST}"
    
    PGPASSWORD='<metastore-password>' pg_dump -h 127.0.0.1 -U risingwave \
      -F custom -f "${DEST}/risingwave_meta.dump" risingwave_meta
    
    mc mirror local/hummock "${DEST}/hummock/"
    cp -a /etc/risingwave "${DEST}/etc-risingwave"

    Prometheus metrics on 127.0.0.1:1250/metrics; built-in dashboard on 127.0.0.1:5691 (SSH tunnel).