Kör en Valkey-server med Podman utan root

Valkey 9.1 på Debian 13, Redis-forken med öppen källkod, i rootless Podman under en egen användare, med en inloggning per app, anpassad för 8 GB, nåbar bara från servern och via WireGuard, och nattliga ögonblicksbilder du har återställt.

Testad på Valkey 9.1.2 på Debian 13 (trixie) på en server hos Melonslab Uppdaterad 14 oktober 2026

Rekommenderad server för guiden

SSD RAID 1 · ECC DDR4 · 10 Gbit

VC-P Alloy · 2 vCPU · 8 GB Minne · 60 GB Lagring

Månadsvis, ingen bindningstid 7 dagars öppet köp

100 kr/mån

Beställ nu
På den här sidan

Det här sätter du upp

Valkey är en nyckel-värde-databas som håller allt i minnet: appar använder den som cache, för sessioner, jobbköer, räknare och gränser för antal anrop. Den svarar på långt under en millisekund eftersom allt ligger i minnet, och den sparar till disk så att datan finns kvar efter en omstart. Appar som stöder Redis fungerar med Valkey utan ändringar.

Valkey startade i mars 2024, när Redis lämnade öppen källkod, som en fork av Redis 7.2.4. Det är ett projekt under Linux Foundation som utvecklas öppet på GitHub, med utvecklare från bland andra AWS, Google och Oracle, och det är öppen källkod under BSD-licensen med tre klausuler. Valkey kontaktar ingen tjänst på internet: när vi avlyssnade testserverns trafik medan Valkey startade och betjänade en app var den enda utgående trafiken serverns egen tidssynkronisering.

Här körs Valkey från sin officiella avbild, i Podman under en egen användare som heter valkey, med en inloggning för varje app och den inbyggda användaren default avstängd. Den lyssnar bara på servern själv och på dess WireGuard-adress, aldrig på den publika adressen.

Varje steg nedan har körts på en nyinstallerad Melonslab VC-P Alloy (2 vCPU, 8 GB) med Debian 13:

  • Valkey 9.1.2 startade med sina användare från en hemlighet i Podman. En anslutning utan användarnamn fick NOAUTH Authentication required., och användaren default nekades.
  • Appens inloggning kunde läsa och skriva, men inte köra CONFIG, SHUTDOWN eller ACL. En andra apps inloggning, begränsad till nycklar som börjar med shop:, fick NOPERM på den första appens nycklar.
  • En appserver på WireGuard anslöt med valkey-cli och ett Python-skript, och vår dator genom en SSH-tunnel. Från internet fick port 6379 på den publika adressen inget svar.
  • Med 1 GB testdata mätte vi vad varje sätt att spara kostar, och kontrollerade att maxmemory nekar skrivningar, eller kastar ut gamla nycklar, när minnet är fullt.
  • Efter en omstart av servern fanns alla 10 000 testposter kvar. En nattlig ögonblicksbild återställdes till en tom volym, och en uppdatering från 9.0 till 9.1 behöll datan.

Efter en omstart använde hela servern omkring 470 MB minne, varav Valkey 9 MB med våra 10 000 poster. Valkey växer med din data, upp till gränsen på 4 GB som ställs in i steg 3.

Innan du börjar

Du behöver:

Du behöver inget DNS-namn: apparna ansluter till en IP-adress som bara de kan nå.

Exemplen använder 203.0.113.10 för serverns publika adress, 10.8.0.1 för dess WireGuard-adress, 10.8.0.2 för en appserver på WireGuard och app för appens inloggning. Byt ut dem genomgående.

1. Förbered servern

Som root skapar du /etc/sysctl.d/60-valkey.conf:

# Let Valkey save snapshots without failing when memory is tight
vm.overcommit_memory = 1
# Let Valkey listen on the WireGuard address before the tunnel is up
net.ipv4.ip_nonlocal_bind = 1
sysctl --system
  • För att spara till disk kopierar Valkey sig själv i minnet med fork. Linux standardinställning kan neka den kopian när minnet ser ut att ta slut, och då misslyckas sparningen. Valkeys dokumentation kräver 1, och utan den skriver Valkey WARNING Memory overcommit must be enabled! i loggen vid varje start.
  • Vid uppstart får containern inte vänta in WireGuard, och Podman kan inte lyssna på 10.8.0.1 innan adressen finns. Den andra raden tillåter det, och anslutningar fungerar så snart tunneln är uppe. Utan den startar inte Valkey om den hinner före WireGuard (se Felsökning).

Skapa sedan användaren:

useradd -m -s /bin/bash valkey
loginctl enable-linger valkey
machinectl shell valkey@

Allt fram till steg 6 körs som valkey.

2. Skapa inloggningarna

Valkeys inbyggda användare default har inget lösenord och får köra alla kommandon. Stäng av den och ge varje app en egen inloggning. Valkey läser dem från en ACL-fil, som du lagrar som en hemlighet i Podman, så att inget lösenord hamnar i en egen fil:

admin=$(openssl rand -hex 32)
app=$(openssl rand -hex 32)
printf %s "$admin" | podman secret create valkey-admin-password -
printf '%s\n' 'user default off' "user admin on >$admin ~* &* +@all" "user app on >$app ~* &* +@all -@admin" | podman secret create valkey-users -
unset admin app

Det ger tre användare:

  • default är avstängd, så ingen kan använda Valkey utan användarnamn och lösenord.
  • admin får göra allt. Den använder du för säkerhetskopior och ändringar, från servern själv.
  • app får använda alla nycklar (~*) och alla kanaler (&*), och alla kommandon utom de i gruppen @admin: CONFIG, ACL, SHUTDOWN, SAVE, MONITOR, DEBUG, replikering och liknande. Kommandon som KEYS, INFO och FLUSHDB är fortfarande tillåtna, eftersom många appar och bibliotek använder dem.

Adminlösenordet lagras också för sig, så att valkey-cli i containern kan logga in som admin utan att du skriver det. För att se lösenorden, till appens inställningar:

podman secret inspect --showsecret --format '{{.SecretData}}' valkey-users

Lösenordet står efter >. Valkey håller bara en SHA-256-hash av det i minnet.

3. Ställ in minne och lagring

Skapa ~/valkey.conf:

# Users and passwords come from the valkey-users secret
aclfile /run/secrets/valkey-users

# Memory: at most 4 GB of data, and refuse writes when it is full
maxmemory 4gb
maxmemory-policy noeviction

# Persistence: a log of every write, flushed to disk every second,
# and a snapshot every hour, or sooner after many changes
appendonly yes
appendfsync everysec
save 3600 1 300 100 60 10000
dir /data

Minne. Valkey håller all sin data i minnet, och utan en gräns tar den vad den behöver tills Linux stoppar den. Varje gång den sparar delar kopian den gör med fork minne med Valkey, men varje nyckel som ändras medan sparningen pågår tar minne två gånger. I vårt test med 1 GB data kopierade en omskrivning av AOF-filen under tung skrivning 845 MB, nästan allt, medan samma sparning på en lugn server kopierade 34 MB. Håll därför lika mycket minne ledigt som Valkey får använda: på en server med 8 GB blir det 4 GB för Valkey. Kör andra appar på samma server sänker du gränsen.

När minnet är fullt avgör maxmemory-policy:

  • noeviction, som används här, nekar skrivningar med OOM command not allowed when used memory > 'maxmemory' och behåller allt. Använd den när Valkey har sessioner, köer eller annat som din app inte får förlora.
  • allkeys-lru tar bort de nycklar som använts minst nyligen för att få plats. Använd den när Valkey bara är en cache, där en saknad nyckel hämtas på nytt. Vi såg den kasta ut gamla nycklar och ta emot den nya vid gränsen.
  • volatile-lru tar bara bort nycklar som har en utgångstid, för en blandning av de två.

Lagring. Valkey har två sätt att spara, och den här konfigurationen använder båda:

  • Ögonblicksbilder (RDB): hela datamängden skriven till en kompakt fil, här varje timme om något har ändrats, var 5:e minut efter 100 ändringar och varje minut efter 10 000. Efter en krasch förlorar du det som ändrats sedan den senaste ögonblicksbilden. Vår ögonblicksbild på 1 GB tog 13 till 19 sekunder att skriva och blev en fil på 990 MB. Det är dem säkerhetskopian i steg 8 kopierar.
  • Loggfilen (AOF): varje skrivning läggs också till i en logg, som appendfsync everysec skriver till disk en gång i sekunden. Efter en krasch förlorar du som mest ungefär en sekund. Loggen växer tills Valkey skriver om den som en ögonblicksbild plus nya skrivningar, av sig själv när den har fördubblats.

Vi mätte kostnaden med valkey-benchmark, 50 klienter som skriver värden på 100 byte:

LagringSkrivningar per sekund
Bara ögonblicksbilder55 000
AOF, everysec46 500
AOF, always9 700

appendfsync always väntar på disken vid varje skrivning och förlorar ingenting, med en femtedel av farten. För en ren cache som kan byggas upp igen sparar appendonly no in skrivningarna till disk. En omstart tar längre tid med mer data: Valkey svarar LOADING Valkey is loading the dataset in memory tills den har läst in allt. För vår 1 GB små nycklar, 8,6 miljoner stycken, tog det 24 sekunder direkt efter att loggfilen hade skrivits om, och 39 sekunder när den innehöll många skrivningar sedan dess.

4. Definiera containern

mkdir -p ~/.config/containers/systemd

Skapa ~/.config/containers/systemd/valkey.container:

[Unit]
Description=Valkey

[Container]
ContainerName=valkey
Image=docker.io/valkey/valkey:9.1
Exec=valkey-server /etc/valkey/valkey.conf
Volume=%h/valkey.conf:/etc/valkey/valkey.conf:ro
Volume=valkey-data:/data
Secret=valkey-users
Secret=valkey-admin-password,type=env,target=VALKEYCLI_AUTH
# Only this server and WireGuard devices can reach Valkey: the port is not open to the internet.
PublishPort=127.0.0.1:6379:6379
PublishPort=10.8.0.1:6379:6379
AutoUpdate=registry

[Service]
Restart=always

[Install]
WantedBy=default.target
  • Secret=valkey-users lägger ACL-filen på /run/secrets/valkey-users i containern, där valkey.conf läser den.
  • VALKEYCLI_AUTH är variabeln som valkey-cli hämtar sitt lösenord från.
  • De två raderna PublishPort avgör vem som kan ansluta: servern själv på 127.0.0.1 och enheter på WireGuard på 10.8.0.1. Valkey lyssnar inte alls på den publika adressen. Utan WireGuard tar du bort den andra raden.
  • Taggen 9.1 ger alla fel- och säkerhetsrättningar i Valkey 9.1, och inget mer. Steg 9 har detaljerna.

Starta den:

systemctl --user daemon-reload
systemctl --user start valkey
systemctl --user enable --now podman-auto-update.timer
podman exec valkey valkey-cli --user admin ping

Den svarar PONG. Utan användarnamn får du användaren default, som är avstängd:

podman exec valkey valkey-cli ping
AUTH failed: WRONGPASS invalid username-password pair or user is disabled.
NOAUTH Authentication required.

5. Släpp in dina appar

Via WireGuard. Gå tillbaka till root med exit och öppna port 6379 bara i tunneln:

ufw allow in on wg0 to any port 6379 proto tcp

På appservern, som har tunneladressen 10.8.0.2, finns valkey-cli i Debians paket valkey-tools:

apt install -y valkey-tools
valkey-cli -h 10.8.0.1 --user app --askpass

--askpass frågar efter lösenordet, så att det inte blir kvar i skalets historik. Sedan:

10.8.0.1:6379> set greeting hello
OK
10.8.0.1:6379> get greeting
"hello"
10.8.0.1:6379> config get maxmemory
(error) NOPERM User app has no permissions to run the 'config|get' command

I en app är anslutningsadressen redis://app:PASSWORD@10.8.0.1:6379/0. De flesta Redis-bibliotek tar den som den är, och en del nyare tar även valkey://. Trafiken krypteras av WireGuard.

Appar i containrar på den här servern. Inne i en container är 127.0.0.1 containern själv. Använd 10.8.0.1 i stället: serverns WireGuard-adress går att nå från rootless-containrar, vilket vi kontrollerade från en container under en annan användare.

Från din egen dator, genom SSH. En SSH-tunnel kräver ingen ändring på servern:

ssh -N -L 6380:localhost:6379 root@203.0.113.10

Medan den körs ansluter du i en annan terminal till port 6380 på din egen dator:

valkey-cli -p 6380 --user app --askpass

Port 6380 används för att inte krocka med en Valkey eller Redis på din egen dator.

Om TLS. Valkey kan kryptera anslutningar själv, med tls-port och ett certifikat. Den här guiden använder det inte: WireGuard och SSH krypterar redan allt som lämnar servern, och anslutningar på 127.0.0.1 lämnar den aldrig. Öppna inte port 6379 mot internet i stället, varken med eller utan TLS.

6. Kontrollera vad andra ser

På servern, som root:

ss -tlnp | grep 6379
LISTEN 0      128          10.8.0.1:6379      0.0.0.0:*    users:(("pasta.avx2",pid=2814,fd=7))
LISTEN 0      128         127.0.0.1:6379      0.0.0.0:*    users:(("pasta.avx2",pid=2814,fd=6))

pasta är programmet som skickar vidare anslutningar in i containern. Bara de två adresserna: inget på 0.0.0.0, [::] eller den publika adressen. Från en dator som inte är med i VPN:et:

nc -zv -w 10 203.0.113.10 6379
nc: connect to 203.0.113.10 port 6379 (tcp) timed out: Operation now in progress

ufw släpper försöket utan att svara, och på servern visar journalctl -k | grep 'DPT=6379' det som [UFW BLOCK]. Valkey lyssnar inte heller där, så porten är stängd även om brandväggen skulle vara avslagen.

7. Anslut från en app

Ett exempel i Python, med biblioteket valkey, Valkey-projektets fork av redis-py. På appservern:

python3 -m venv ~/venv
~/venv/bin/pip install valkey

Skapa app.py:

import os
import valkey

r = valkey.Valkey(
    host=os.environ.get("VALKEY_HOST", "10.8.0.1"),
    port=6379,
    username="app",
    password=os.environ["VALKEY_PASSWORD"],
    decode_responses=True,
)

r.set("greeting", "Hello from the app")
print(r.get("greeting"))

# A counter, and a list used as a simple queue
print("visits:", r.incr("visits"))
r.lpush("jobs", "send-invoice:1042")
print("next job:", r.rpop("jobs"))
read -rs VALKEY_PASSWORD && export VALKEY_PASSWORD
~/venv/bin/python app.py
Hello from the app
visits: 1
next job: send-invoice:1042

Biblioteket redis fungerar också: vi körde samma skript med redis.Redis(...) och samma argument.

En inloggning för varje app

Ge en andra app en egen inloggning, begränsad till nycklar som börjar med dess eget prefix. Som valkey lägger du till en rad i hemligheten och startar om:

{ podman secret inspect --showsecret --format '{{.SecretData}}' valkey-users; echo "user shop on >$(openssl rand -hex 32) ~shop:* &shop:* +@all -@admin -flushall -flushdb"; } | podman secret create --replace valkey-users -
systemctl --user restart valkey

shop kan nu bara läsa och skriva nycklar som shop:cart:1, och GET user:42 får NOPERM No permissions to access a key. -flushall -flushdb behövs här: de två kommandona tömmer hela databasen, oavsett vad nyckelgränserna säger. KEYS och SCAN listar fortfarande namnen på alla nycklar, men inte deras värden. Appar som inte ens får se varandras nyckelnamn behöver en egen Valkey.

8. Säkerhetskopiera varje natt

En ögonblicksbild kan tas från den Valkey som körs, medan apparna fortsätter att använda den. Skapa ~/valkey-backup:

#!/bin/sh
# Save a snapshot of Valkey, and keep 14 days of them
set -e
umask 077
mkdir -p ~/backup
podman exec valkey valkey-cli --user admin --rdb /tmp/backup.rdb
podman cp valkey:/tmp/backup.rdb ~/backup/valkey-$(date +%F).rdb
podman exec valkey rm /tmp/backup.rdb
find ~/backup -name 'valkey-*.rdb' -mtime +13 -delete

valkey-cli --rdb ber Valkey om en ny ögonblicksbild, som en replik skulle göra. Den skrivs först till en fil i containern: skickad direkt till skärmen, med -, fick ögonblicksbilden 40 extra byte på slutet. Kör skriptet varje natt med en egen timer för användaren. Skapa ~/.config/systemd/user/valkey-backup.service:

[Unit]
Description=Back up Valkey

[Service]
Type=oneshot
ExecStart=%h/valkey-backup

Och ~/.config/systemd/user/valkey-backup.timer:

[Unit]
Description=Back up Valkey every night

[Timer]
OnCalendar=*-*-* 02:30
Persistent=true

[Install]
WantedBy=timers.target
chmod 755 ~/valkey-backup
systemctl --user daemon-reload
systemctl --user enable --now valkey-backup.timer
systemctl --user start valkey-backup.service
ls -l ~/backup
-rw-r--r-- 1 valkey valkey 646899 Oct 14 01:45 valkey-2026-10-14.rdb

Spara också inloggningarna en gång, eftersom en ny server behöver dem och dina appar känner till lösenorden:

podman secret inspect --showsecret --format '{{.SecretData}}' valkey-users > ~/backup/users.acl

Kopiera ~/backup till en annan maskin, till exempel med restic, och förvara den säkert: den innehåller all din data och lösenorden.

Testa en återställning. När AOF är påslaget och dess katalog saknas startar Valkey tom och struntar i en ögonblicksbild bredvid. Det var precis vad vi såg: den första återställningen kom upp utan nycklar. Stäng därför av AOF vid den första starten och slå på det igen när datan är inläst. Som valkey, med ögonblicksbilden i ~/backup:

systemctl --user stop valkey
podman volume rm valkey-data
podman volume create valkey-data
podman run --rm -v valkey-data:/data -v ~/backup:/backup:ro docker.io/valkey/valkey:9.1 cp /backup/valkey-2026-10-14.rdb /data/dump.rdb
sed -i 's/^appendonly yes/appendonly no/' ~/valkey.conf
systemctl --user start valkey
podman exec valkey valkey-cli --user admin dbsize
podman exec valkey valkey-cli --user admin config set appendonly yes
sed -i 's/^appendonly no/appendonly yes/' ~/valkey.conf

dbsize visar hur många nycklar som kom tillbaka: alla våra 10 002. config set appendonly yes skriver en ny AOF-fil från datan i minnet. Vänta tills podman exec valkey valkey-cli --user admin info persistence | grep aof_rewrite_in_progress visar 0 innan du startar om Valkey. På en ny server skapar du valkey-users från users.acl i steg 2, med podman secret create valkey-users ~/backup/users.acl, och valkey-admin-password från adminlösenordet i den.

9. Uppdatera

podman auto-update letar en gång om dagen efter en ny avbild under taggen 9.1 och startar om Valkey när det finns en: de mindre versionerna med fel- och säkerhetsrättningar. För att se vad den skulle göra just nu:

podman auto-update --dry-run

En ny delversion, som 9.2, eller en ny huvudversion kräver att du byter tagg. Gör en säkerhetskopia, läs versionsinformationen på GitHub, ändra Image= i valkey.container och starta om:

systemctl --user daemon-reload
systemctl --user restart valkey
podman exec valkey valkey-cli --user admin info server | grep valkey_version

Vi testade en uppdatering från 9.0.6 till 9.1.2 på det här sättet, och datan följde med. Att gå tillbaka till en äldre version fungerar inte säkert, eftersom en nyare Valkey kan skriva ögonblicksbilder som en äldre inte kan läsa: det är därför du har säkerhetskopian. Använd bara rena versionstaggar som 9.1: när vi testade pekade taggen 9.2 på en testversion, 9.2.0-rc1.

Felsökning

Valkey startar inte efter en omstart, och loggen säger Failed to bind port 6379 (Cannot assign requested address) for option '-t 10.8.0.1/6379-6379:6379-6379'. Valkey startade före WireGuard, och net.ipv4.ip_nonlocal_bind är inte satt. Kontrollera att sysctl net.ipv4.ip_nonlocal_bind visar 1 (steg 1), och kör sedan systemctl --user reset-failed valkey och systemctl --user start valkey som valkey.

NOAUTH Authentication required. eller WRONGPASS invalid username-password pair or user is disabled. Klienten ansluter utan användarnamn, som default, eller med fel lösenord. Ange användarnamnet app utöver lösenordet. Med valkey-cli 8.1 från Debian 13 kräver --user antingen --askpass eller --pass; variabeln VALKEYCLI_AUTH används inte tillsammans med den.

NOPERM User app has no permissions to run the '...' command. Kommandot ingår i gruppen @admin. Kör det som admin på servern, eller lägg till det på appens rad i hemligheten om appen verkligen behöver det, till exempel +config|get, och starta om.

OOM command not allowed when used memory > 'maxmemory'. Valkey är full. Höj maxmemory om servern har minne över, ta bort data, eller använd allkeys-lru om Valkey bara är en cache (steg 3).

LOADING Valkey is loading the dataset in memory. Valkey har just startat och läser fortfarande in sin data från disk. Vänta: det tog 24 till 39 sekunder för 1 GB på vår server.

Datan är borta efter en återställning. AOF var påslaget vid den första starten. Börja om från stegen för återställning, med appendonly no vid den första starten.

En appserver får Connection timed out mot 10.8.0.1. Kontrollera med wg show att WireGuard är uppe i båda ändar, och att ufw har regeln från steg 5.

Kör det på din egen server

SSD RAID 1 · ECC DDR4 · 10 Gbit

VC-P Alloy

100 kr/mån

vCPU
2
Minne
8 GB
Lagring
60 GB
Trafik
10 TB
Performance
SSD · RAID 1
  • Full root-åtkomst
  • Nativt /64 IPv6
  • RAID-skyddad lagring
  • Malmö, Sverige
  • Månadsvis, ingen bindningstid
  • 7 dagars öppet köp
Alla guider