Jinsi ya kujiendeshea AFFiNE kwa Docker Compose
Jifunze kuendesha AFFiNE kwenye VPS moja kwa kutumia Docker Compose. Mwongozo huu unaelezea usanidi wa kontena nne, matumizi ya RAM ya 2 GB, na jinsi ya kuhifadhi data zako.
Unachopata unapojiendeshea AFFiNE mwenyewe
Kujiendeshea AFFiNE kwenye seva yako kunakupa nafasi ya kazi ya mtindo wa Notion kwenye seva unayoimiliki, inayofanya kazi kama kontena nne: programu yenyewe, kazi ya uhamiaji (migration job) ya mara moja, Postgres, na Redis. Ushirikiano wa wakati halisi umejumuishwa, hadi viti 10 ambavyo nafasi ya kazi inayojiendeshea yenyewe hupata kwa chaguo-msingi. Usakinishaji unahusisha faili moja ya compose na faili moja ya usanidi ya JSON. Mambo yanayohitaji kufikiriwa ni tag za image, mpangilio wa diski, ukomo wa kumbukumbu (memory ceiling), na proxy unayoiweka mbele.
AFFiNE huweka kihariri cha hati na ubao usio na kikomo (infinite canvas) katika nafasi moja ya kazi, kwa hivyo ukurasa mmoja unaweza kusomwa kama hati au kutandazwa kama ubao mweupe. Ikiwa bado unaamua nini cha kuendesha, soma ulinganisho wa njia mbadala za Notion zinazojiendesha kwanza. Mwongozo huu unachukulia kuwa uamuzi umeshafanyika, na unahusu kuendesha AFFiNE ipasavyo badala ya kuilinganisha tena.
Kila kitu hapa kimehakikiwa dhidi ya nyaraka za kujiendeshea za AFFiNE na faili za toleo zilizochapishwa mnamo 8 Agosti 2026. Toleo jipya zaidi la stable katika tarehe hiyo lilikuwa 0.27.3, lililochapishwa mnamo 23 Julai 2026.
Kazi halisi ya containers nne
affine ni seva na web client katika image moja. Inasikiliza kwenye port 3010.
affine_migration ni kazi ya mara moja inayotekeleza node ./scripts/self-host-predeploy.js, inafanya migrations za database, na kisha inajifunga. Programu inatangaza condition: service_completed_successfully kwenye kazi hiyo, hivyo migration inayofeli (non-zero status) inamaanisha affine haitaanza kabisa. Ikiwa interface ya web haifunguki, log ya kazi hiyo ndiyo ya kwanza kusoma.
postgres inahifadhi hati, watumiaji, workspaces na ruhusa zako. Image inayotolewa ni pgvector/pgvector:pg16, ambayo ni Postgres 16 ya kawaida ikiwa na pgvector extension iliyojumuishwa. pgvector inaongeza aina ya safu (column type) ya vector kwenye Postgres, mfumo wa namba unaotumika kuhifadhi embeddings ili maandishi yaweze kutafutwa kwa maana.
redis ni dependency muhimu: seva na kazi ya migration zote husubiri health check yake kabla ya kuanza. Angalia kile ambacho compose file inayotolewa haitoi kwa Redis, nacho ni volume. Hakuna kitu ndani yake kinachobaki baada ya docker compose down, na hilo linakuambia wazi kuwa haihifadhi maudhui yako yoyote na haihitaji backup.
Kwa nini image ya Postgres ni pgvector na siyo stock postgres
Sharti hili linatokana na schema ya AFFiNE, siyo kwa sababu ya upendeleo. Katika schema.prisma chanzo cha data kinatangaza extensions = [pgvector(map: "vector")], na majedwali manne yana safu ya embedding yenye aina ya vector(1024). Kazi ya migration hutengeneza majedwali hayo bila kujali kama umewasha vipengele vya AI au la, kwa hivyo extension lazima iwepo kwenye database kabla ya migration kukamilika. Ukibadilisha na postgres:16 extension hiyo haitakuwepo, migration haitaweza kutengeneza safu hizo, na seva itabaki ikisubiri kazi iliyofeli.
AFFiNE ilihamia kwenye image ya pgvector kuanzia toleo la 0.21. Kwenye usakinishaji wa zamani zaidi ya huo, kuhariri mstari wa image siyo uboreshaji kamili, kwa hivyo soma ukurasa wa uboreshaji katika nyaraka za self-host za AFFiNE kabla ya kuvuta chochote.
Jambo lingine kuhusu tag hiyo. pg16 inamaanisha Postgres 16, na toleo kuu (major version) la Postgres siyo namba unayoweza kuibadilisha kiholela. Ukibadilisha kuwa pg17 juu ya saraka ya data iliyopo, Postgres itakataa kuanza, ikiwa na mstari kama The data directory was initialized by PostgreSQL version 16, which is not compatible with this version 17 katika docker compose logs postgres. Kuhama toleo kuu kunamaanisha kufanya dump na restore kwenye saraka mpya ya data.
AFFiNE inayojiendesha yenyewe inahitaji CPU na RAM kiasi gani
Ukurasa wa mahitaji ya AFFiNE unaelekeza kuwa unahitaji angalau cores 4 za CPU na 2 GB ya RAM, na huongeza kumbukumbu hadi 4 GB pindi hati zako zinapozidi maneno 10,000. Ukurasa huo huo unaeleza mahali ambapo kumbukumbu hutumika: mfumo wa kusawazisha (sync) na kuunganisha hati (document merging). Unatoa takwimu moja muhimu ya kukumbuka, nayo ni kwamba kuunganisha hati yenye marekebisho 10,000 kunaweza kufikia kilele cha 1 GB.
Sasa linganisha takwimu hizo na mpango wa 2 GB kwa watu wawili wanaoandika. Wastani unatosha. Postgres na mchakato wa Node hukaa chini ya kikomo hicho na kubakiza nafasi. Tatizo ni kilele cha matumizi. Unganisho moja kubwa la hati linaweza kuhitaji 1 GB zaidi ya kile kilichopo kwenye kumbukumbu, na kwenye seva ya 2 GB isiyo na swap, kiondoa mchakato cha kernel (OOM killer) hujibu ombi hilo kwa kuua mchakato mkubwa zaidi, ambao ni seva ya AFFiNE.
Mfanyakazi mwenzako hataona kosa. Ataona ukurasa ukijipakia upya, kwa sababu restart: unless-stopped huirudisha container ndani ya sekunde chache. Usikisie hili, lithibitishe:
docker inspect affine_server --format '{{.State.OOMKilled}} {{.RestartCount}}'
sudo dmesg -T | grep -i -E 'out of memory|killed process'true kutoka kwa amri ya kwanza, au mstari wa Killed process unaotaja node kutoka kwa amri ya pili, inamaanisha kuwa ulikosa kumbukumbu badala ya kupata mdudu (bug). Rekebisha hili kwa pande zote mbili. Ongeza swap kwanza, ili ongezeko la ghafla liwe la polepole badala ya kuwa mbaya:
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
free -hfree -h sasa inapaswa kuripoti jumla ya 2.0Gi ya swap. Swap haifanyi AFFiNE kuwa ya haraka, na haikusudiwi kufanya hivyo. Inageuza ongezeko la ghafla la sekunde moja kuwa sekunde ya polepole badala ya container iliyokufa. Upande mwingine wa marekebisho ni kuzuia Postgres kukuza cache yake kwenye nafasi ambayo programu inahitaji wakati wa kuunganisha hati, jambo ambalo ndilo vikomo vya kumbukumbu kwenye huduma ya Compose vinahusu.
Hifadhi (storage) ni rahisi zaidi kutabiri. Hizi ndizo takwimu ambazo AFFiNE inachapisha kwenye ukurasa huo huo:
The data behind this chart
[
{
"label": "Server install",
"gb": 1.5
},
{
"label": "Postgres per 1,000 docs",
"gb": 0.1
},
{
"label": "Blob store per 1,000 uploads",
"gb": 10
}
]Ufungaji wa seva unachukua 1.5 GB. Hati elfu moja zenye takriban maneno elfu moja kila moja huongeza 0.1 GB ya data ya Postgres, ambayo ni karibu sawa na sifuri. Faili elfu moja zilizopakiwa huongeza 10 GB, ambayo ndiyo hadithi nzima. Hizi ni takwimu za kupanga zilizochapishwa badala ya vipimo kutoka kwa mfano unaoendesha, kwa hivyo zichukulie kama mwongozo na si ahadi. Mwongozo ndio muhimu: hifadhidata yako inabaki ndogo, na faili unazopakia ndizo zinazoamua nafasi ya diski yako.
Andika faili ya compose mwenyewe, ukiwa umefunga matoleo (tags)
Usakinishaji uliopendekezwa hupakua faili iliyoandaliwa tayari kwa kutumia curl -L -o docker-compose.yml https://github.com/toeverything/AFFiNE/releases/latest/download/docker-compose.yml. Hiyo inafanya kazi. Kuna jambo moja la kuzingatia kabla ya kuitegemea: kufikia tarehe 8 Agosti 2026, faili iliyoambatishwa kwenye toleo la 0.27.3 bado inasoma njia zake (paths) kutoka kwenye faili ya .env, ikitumia ${UPLOAD_LOCATION}, ${CONFIG_LOCATION} na ${DB_DATA_LOCATION}, wakati ukurasa wa marejeleo wa nyaraka hizo unaonyesha mpangilio mpya zaidi unaoweka kila kitu chini ya ./data na hauhitaji .env hata kidogo. Zote mbili ni halali. Kuandika faili mwenyewe kunamaliza utata huo, na lazima uihariri ili kufunga matoleo ya images na kuweka nenosiri la database.
mkdir -p ~/affine/config ~/affine/data
cd ~/affine
printf 'DB_PASSWORD=%s\n' "$(openssl rand -hex 24)" > .env
chmod 600 .envCompose inasoma .env kutoka kwenye saraka ya mradi yenyewe na kubadilisha ${DB_PASSWORD} kwa ajili yako, hivyo nenosiri halionekani kamwe kwenye faili unayoweza kuibandika kwenye jukwaa la usaidizi. Tabia hiyo inafaa kudumishwa katika kila stack unayoendesha, na sababu zake ziko katika kuepuka kuweka siri kwenye faili ya compose.
Sasa andika ~/affine/docker-compose.yml:
name: affine
services:
affine:
image: ghcr.io/toeverything/affine:stable
container_name: affine_server
ports:
- '127.0.0.1:3010:3010'
depends_on:
redis:
condition: service_healthy
postgres:
condition: service_healthy
affine_migration:
condition: service_completed_successfully
volumes:
- ./data/storage:/root/.affine/storage
- ./config:/root/.affine/config
environment:
- REDIS_SERVER_HOST=redis
- DATABASE_URL=postgresql://affine:${DB_PASSWORD}@postgres:5432/affine
- AFFINE_INDEXER_ENABLED=false
restart: unless-stopped
affine_migration:
image: ghcr.io/toeverything/affine:stable
container_name: affine_migration_job
command: ['sh', '-c', 'node ./scripts/self-host-predeploy.js']
volumes:
- ./data/storage:/root/.affine/storage
- ./config:/root/.affine/config
environment:
- REDIS_SERVER_HOST=redis
- DATABASE_URL=postgresql://affine:${DB_PASSWORD}@postgres:5432/affine
- AFFINE_INDEXER_ENABLED=false
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
redis:
image: redis:8-alpine
container_name: affine_redis
healthcheck:
test: ['CMD', 'redis-cli', '--raw', 'incr', 'ping']
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
postgres:
image: pgvector/pgvector:pg16
container_name: affine_postgres
volumes:
- ./data/postgres:/var/lib/postgresql/data
environment:
POSTGRES_USER: affine
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: affine
POSTGRES_INITDB_ARGS: '--data-checksums'
healthcheck:
test: ['CMD', 'pg_isready', '-U', 'affine', '-d', 'affine']
interval: 10s
timeout: 5s
retries: 5
restart: unless-stoppedKuna tofauti nne kutoka kwenye faili inayotolewa na wasanidi, na kila moja ina sababu yake.
127.0.0.1:3010:3010inachapisha port kwenye loopback address pekee, hivyo hakuna kitu nje ya seva kinachoweza kufikia AFFiNE hadi utakapoamua jinsi ya kufanya hivyo. Faili ya awali ya'3010:3010'inafungamanisha (bind) kila interface, na kwenye picha nyingi za VPS hiyo inajumuisha ile ya umma.POSTGRES_HOST_AUTH_METHOD: trustimeondolewa na nenosiri limewekwa badala yake. Uthibitishaji wa aina ya trust unakubali muunganisho wowote kwenye database hiyo kama mtumiajiaffinebila nenosiri. Hii imepunguzwa kwenye mtandao wa ndani wa Compose, jambo ambalo ni sawa hadi siku utakapounganisha container nyingine kwenye mtandao huo au kuchapisha 5432 wakati wa kutatua hitilafu (debugging).redis:8-alpineinachukua nafasi yaredistupu, ambayo inatafsiriwa kamalatest. Kufikia Agosti 2026, hiyo ni Redis 8, kwa hivyo kufunga toleo (pin) kunahifadhi toleo kuu ulilolijaribu na kuzuia Redis 9 kuingia wakati wadocker compose pullisiyohusiana.pgvector/pgvector:pg16inabaki kama ilivyowekwa na wasanidi, kwa sababu iliyotajwa hapo juu.
POSTGRES_PASSWORD inasomwa tu wakati Postgres inapotengeneza saraka yake ya data kwa mara ya kwanza. Kwenye mfumo uliopo tayari, weka nenosiri kwa kutumia docker compose exec postgres psql -U affine -c "ALTER USER affine WITH PASSWORD 'yourpassword'" kisha usasishe DATABASE_URL ili ilingane.
Usanidi unapatikana katika config/config.json
AFFiNE inasoma mipangilio yake kutoka config/config.json, ambayo ni saraka uliyoiweka (mount) kwenye /root/.affine/config. Hakuna kinachotengeneza faili hiyo kwa ajili yako, kwa hivyo iandike kabla ya kuanza kwa mara ya kwanza. Fungua ~/affine/config/config.json katika kihariri na uweke maudhui haya, ukitumia domain yako badala ya mfano huu:
{
"$schema": "https://github.com/toeverything/affine/releases/latest/download/config.schema.json",
"server": {
"name": "Team workspace",
"externalUrl": "https://affine.example.com"
},
"copilot": {
"enabled": false,
"byok": {
"enabled": false
}
}
}server.externalUrl lazima iwe anwani ambayo watumiaji wako wanaifungua kwenye kivinjari. AFFiNE hutengeneza viungo vya kushiriki (share links) na mialiko ya workspace kutoka kwa thamani hiyo, kwa hivyo ikiachwa kama http://localhost:3010, mwaliko unaotuma utamwelekeza mpokeaji kwenye mashine yake mwenyewe na utafeli hapo. Iweke kwenye anwani ya umma ya HTTPS kabla ya kuanza kwa mara ya kwanza, ili faili na paneli ya admin zisikinzane kuhusu hilo.
copilot inadhibiti vipengele vya AI. copilot.byok.enabled ni swichi ya "leta ufunguo wako mwenyewe" (bring-your-own-key), inayomruhusu mmiliki wa workspace kubandika ufunguo wake wa mtoa huduma wa modeli kwenye mipangilio ya workspace. Kujihostia (self-hosting) AFFiNE hakujumuishi usajili wa AI. Acha zote mbili false ikiwa hutaki vipengele hivyo.
Anzisha stack:
docker compose up -d
docker compose psdocker compose ps inapaswa kuorodhesha affine_postgres na affine_redis kama zenye afya (healthy), affine_server kama zinazoendelea (running), na affine_migration_job ikiwa na hali ya exited (0). Msimbo wowote mwingine wa kutoka (exit code) kwenye kazi ya uhamiaji (migration job) ndio wa kufuatiliwa, na logi yake itataja hatua iliyokwama:
docker compose logs affine_migrationBandika picha (image) kabla hujasahau
stable ni tag inayobadilika. Workflow ya release ya AFFiNE huelekeza tag kadhaa kwenye kila build thabiti, na mbili kati yake ni muhimu hapa: stable, ambayo huelekezwa upya kila wakati release mpya inapotoka, na stable- ikifuatiwa na git short hash, ambayo haibadiliki. Ukiacha kwenye stable, docker compose pull baada ya miezi sita itachota picha tofauti na kuendesha migrations kwenye database yako wakati ambao hukuchagua. Bandika picha kamili uliyofanyia majaribio:
docker compose pull
docker image inspect ghcr.io/toeverything/affine:stable --format '{{index .RepoDigests 0}}'Hiyo itachapisha mstari kama ghcr.io/toeverything/affine@sha256: ikifuatiwa na hash ndefu. Bandika kamba hiyo yote kwenye mstari wa image: katika zote mbili affine na affine_migration. Hizo mbili lazima zilingane kila wakati, kwa sababu ni picha moja inayocheza majukumu mawili, na kutolingana kunamaanisha kuhamishia database kwenye schema moja huku ukiihudumia kwa nyingine. Kuboresha (upgrade) basi kunakuwa ni mabadiliko ya makusudi badala ya mshangao: badilisha digest, fanya backup, docker compose pull, docker compose up -d.
Tengeneza akaunti ya msimamizi kabla ya mtu mwingine yeyote kufanya hivyo
Fungua /admin kwenye instance mpya na AFFiNE itakupeleka kwenye ukurasa wa kutengeneza akaunti, kwa sababu seva haina msimamizi bado. Hakuna invitation code wala setup token katika mtiririko huo. Mtu wa kwanza kupakia ukurasa huo anakuwa msimamizi wa seva yako, kwa hivyo port lazima ibaki imefungwa hadi utakapojisajili.
Hii ndiyo sababu faili ya compose hapo juu inajifunga kwenye 127.0.0.1. Ifikie kupitia SSH tunnel kutoka kwenye mashine yako mwenyewe:
ssh -L 3010:127.0.0.1:3010 you@your-server-ipIache ikifanya kazi na ufungue http://127.0.0.1:3010/admin kwenye kivinjari chako cha ndani. Jisajili na uingie, kisha funga tunnel hiyo. Sasa ndipo inapokuwa salama kuweka instance hiyo kwenye jina la umma.
Mahali ambapo AFFiNE huhifadhi data yako
Njia tatu huhifadhi kila kitu, na zote zinapatikana ndani ya saraka uliyounda.
./data/postgresni saraka ya data ya Postgres: hati, watumiaji, nafasi za kazi (workspaces), na ruhusa../data/storageimewekwa (mounted) kwenye/root/.affine/storagendani ya container na huhifadhi kila faili iliyopakiwa../configimewekwa kwenye/root/.affine/configna huhifadhiconfig.json.
Upstream hutumia bind mounts hapa badala ya named volumes, na chaguo hilo ni la makusudi: unaweza kutumia tar na kunakili njia hizi kwa amri za kawaida, bila kuuliza Docker mahali ilipozihifadhi. Gharama yake ni kwamba umiliki wa faili kwenye host sasa ni jukumu lako, ambalo ni sharti linalofafanuliwa katika bind mounts na named volumes.
Jinsi ya kuhifadhi nakala ya AFFiNE
Kuna vitu viwili vinavyohitaji kuhifadhiwa, na vinahifadhiwa kwa njia tofauti. Database ni seva inayofanya kazi, kwa hivyo kunakili faili zake wakati inaendelea kuendesha kutakupa nakala iliyoharibika. Badala yake, fanya dump:
mkdir -p ~/affine/backup
cd ~/affine
docker compose exec -T postgres pg_dump --format c --username affine affine \
> backup/affine-$(date +%F).dump
ls -lh backup/Dump hiyo inaendeshwa ndani ya container kupitia socket yake ya ndani, kwa hivyo haiombi nenosiri. Angalia ukubwa wa faili katika matokeo ya ls. Faili yenye ukubwa wa baiti chache inaashiria kuwa dump imefeli wakati shell ilitengeneza faili hiyo, jambo ambalo ni kosa ambalo watu huligundua baada ya miezi sita. -T ni muhimu pia: bila hiyo, Compose inaweza kutenga terminal na kuharibu mtiririko wa binary.
Faili zilizopakiwa ni faili za kawaida, kwa hivyo zihifadhi kwa kutumia tar:
tar czf backup/storage-$(date +%F).tgz -C data storage
cp config/config.json backup/config-$(date +%F).jsonHifadhi config.json katika nakala yako kwa mikono. Nyaraka za AFFiNE bado zinaorodhesha usafirishaji wa usanidi kutoka kwenye paneli ya admin kama jambo ambalo halijatekelezwa, kulingana na ukaguzi wa Agosti 2026, kwa hivyo faili iliyo kwenye diski ndiyo nakala pekee ya mipangilio yako. Nakili faili zote tatu nje ya seva. Nakala iliyohifadhiwa kwenye diski moja na kitu inachokilinda si nakala salama.
Kurejesha data, na mtego mmoja katika hatua zilizochapishwa
Soma hatua rasmi za kurejesha data (restore) kabla hujazihitaji, na uzisome kwa umakini. Kama zilivyochapishwa mnamo Agosti 2026, hatua hizo hunakili faili inayoitwa affine.backup ndani ya container na kisha kurejesha kutoka ./pg.backup, ambayo ni majina mawili tofauti, na hufuta saraka ya ./postgres wakati faili ya sasa ya compose huhifadhi data yake katika ./data/postgres. Fuata njia (paths) ulizotumia kihalisi badala ya zile zilizo kwenye kijisehemu cha msimbo. Hii hapa ni mfuatano kulingana na mpangilio katika mwongozo huu:
cd ~/affine
docker compose down
sudo mv data/postgres data/postgres.old
docker compose up -d postgres
docker compose cp backup/affine-2026-08-08.dump postgres:/tmp/affine.dump
docker compose exec postgres pg_restore --format c --username affine \
--dbname affine --verbose /tmp/affine.dump
docker compose up -dZingatia mv badala ya rm. Kurejesha data juu ya database ambayo hujaihifadhi nakala yake ndiyo njia ambayo amri moja mbaya hugeuka kuwa upotevu kamili wa data, na kuhamisha saraka ya zamani pembeni hakugharimu chochote. Rejesha pia faili zilizopakiwa (uploads) kwa kutumia tar xzf backup/storage-2026-08-08.tgz -C data, la sivyo kila hati itaonyesha viambatisho vilivyoharibika. Kisha ingia kwenye mfumo na ufungue hati iliyo na picha. Hiyo ndiyo jaribio. Urejeshaji ambao hujaufungua kwenye kivinjari ni faili tu, si backup.
Kuweka AFFiNE nyuma ya proxy unayotumia tayari
AFFiNE hutumia WebSocket, na hii ni lazima. Nyaraka zake ziko wazi kuhusu hili: WebSocket ndiyo msingi wa mfumo wa usawazishaji na ushirikiano wa AFFiNE, kwa hivyo proxy isiyoboresha (upgrade) miunganisho hiyo itakupa workspace ambapo uhariri utaacha kusawazisha kimya kimya. Ukurasa hupakia, login hufanya kazi, na uhariri uliofanywa kwenye kivinjari kimoja haufiki kwenye kingine. Kwenye zana za msanidi (developer tools) za kivinjari chako, fungua kichupo cha Network na uchuje kwa WS. Muunganisho unaofunguka na kufungika mara kwa mara ni ishara ya proxy isiyopitisha uboreshaji huo.
Ikiwa tayari unatumia Traefik kwa container nyingine, AFFiNE inaweza kujiunga kama huduma ya kawaida. Futa block ya ports: kutoka kwa huduma ya affine, kisha ongeza:
networks:
- default
- proxy
labels:
- 'traefik.enable=true'
- 'traefik.docker.network=proxy'
- 'traefik.http.routers.affine.rule=Host(`affine.example.com`)'
- 'traefik.http.routers.affine.entrypoints=websecure'
- 'traefik.http.routers.affine.tls.certresolver=letsencrypt'
- 'traefik.http.services.affine.loadbalancer.server.port=3010'na chini ya faili, sambamba na services::
networks:
proxy:
external: trueJina la certificate resolver lazima lilingane na lile lililofafanuliwa kwenye usanidi wako wa Traefik, na loadbalancer.server.port ni port ya container ya 3010, si port ya host. Traefik hupitisha miunganisho ya WebSocket bila usanidi wa ziada, kwa hivyo hakuna kingine cha kuongeza. Ikiwa stack yako yote tayari iko nyuma ya Authentik kwa ajili ya single sign-on, middleware ya forward auth kwenye router hii itazuia ufikiaji wa kivinjari kwenda AFFiNE, lakini iache kwanza hadi utakapojaribu programu ya desktop, ambayo haina session ya kivinjari na itashindwa kusawazisha. Kuendesha programu kadhaa nyuma ya instance moja ya Traefik imeelezwa katika Traefik moja mbele ya programu kadhaa.
Kwenye nginx lazima uombe uboreshaji (upgrade) waziwazi:
location / {
proxy_pass http://127.0.0.1:3010;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
client_max_body_size 100m;
}client_max_body_size ina default ya 1 MB kwenye nginx, kwa hivyo bila mstari huo, kila upload kubwa kuliko picha ndogo itafeli na status ya 413 na hakuna kitakachoonekana kwenye log za AFFiNE, kwa sababu ombi hilo halikufika. Caddy inahitaji mstari mmoja tu, reverse_proxy http://127.0.0.1:3010, na inashughulikia certificates pamoja na uboreshaji wa WebSocket yenyewe.
Mambo ambayo toleo la self-hosted halijajumuisha
Kuwa mkweli kwako mwenyewe kuhusu hili kabla ya kuhamisha timu yako.
Ushirikiano wa wakati halisi (real-time collaboration) upo, na ndiyo kipengele kinachozingatiwa katika ushauri wote wa ukubwa wa seva, kwa sababu nyaraka za AFFiNE zenyewe zinahusisha matumizi ya kumbukumbu na mfumo wa kusawazisha (sync) na kuunganisha nyaraka. Kuhariri ukiwa nje ya mtandao (offline) ndiyo sababu watu wengi wanataka zana inayotanguliza matumizi ya ndani (local-first), na programu ya desktop inaweza kuongeza seva yako ya self-hosted kwenye orodha yake ya workspace na kuingia humo. Jaribu tabia kamili ya offline ambayo timu yako inategemea kabla ya kufanya uamuzi: hariri kwenye programu ya desktop huku mtandao ukiwa umezimwa, unganisha tena, kisha angalia matokeo kwenye kifaa cha pili. Orodha za vipengele si ushahidi, na hiyo inajumuisha orodha hii.
Utafutaji wa maandishi kamili (full-text search) upande wa seva umezimwa kwenye faili ya compose iliyosafirishwa, ambapo AFFINE_INDEXER_ENABLED=false imewekwa kwenye seva na kwenye kazi ya uhamiaji (migration job). Kukiwasha kunamaanisha kuongeza container ya Manticore Search, ambayo ni huduma ya tano na inahitaji kumbukumbu zaidi. Kwenye seva ya 2 GB, hicho ndicho kitendo kinachokuvusha mpaka wa uwezo wa seva. Utafutaji ndani ya mteja (client) bado unafanya kazi kwenye workspace uliyofungua.
Kuna mipaka miwili unayopaswa kuijua kabla ya kualika watu. Workspace ya self-hosted inaruhusiwa kuwa na viti (seats) 10 pekee, na kuvuka hapo kunahitaji leseni ya Team kutoka AFFiNE. Hifadhi ya blob isiyo na kikomo na ukubwa wa blob usio na kikomo kwa mifano ya self-hosted imeelezewa kwenye nyaraka kama iliyokusudiwa lakini bado haijatekelezwa kikamilifu, kulingana na ukaguzi wa Agosti 2026. Hakuna kati ya haya yanayohusu kaya au timu ndogo. Yote ni muhimu ikiwa ulikuwa unapanga kuhamisha watu arobaini.
Uboreshaji wa matoleo
Soma maelezo ya toleo kwanza, hasa kwa mabadiliko madogo ya toleo kama kutoka 0.26 kwenda 0.27, ambapo mabadiliko yanayovunja utangamano (breaking changes) hutokea. Hifadhi nakala ya database na saraka ya kuhifadhia data (storage directory) kabla ya kufanya chochote, kwa sababu kazi ya uhamiaji (migration job) hubadilisha schema yako wakati wa kuanza upya na hakuna njia ya kurudisha hali ya awali. Kisha badilisha digest iliyofungwa (pinned digest), endesha docker compose pull ikifuatiwa na docker compose up -d, na ufuatilie docker compose logs -f affine_migration hadi itakapomaliza kazi yake kwa usahihi. docker image prune hufuta matabaka (layers) ya zamani baada ya hapo. Kumbukumbu moja ya kihistoria kwa yeyote aliye na usakinishaji wa zamani sana: kuanzia toleo la 0.23.0 jina la image lilibadilika kutoka affine-graphql kwenda affine, kwa hivyo faili ya compose iliyo ya zamani zaidi ya hapo inahitaji mistari yake ya image iandikwe upya kabla ya amri ya pull kupata kitu chochote.
FAQ
Kwa nini container ya AFFiNE haianziki kamwe?
Huduma ya affine inatangaza condition: service_completed_successfully kwenye kazi ya affine_migration, kwa hivyo ikiwa migration itatoka na status yoyote isiyo 0, seva haitaanza na interface ya wavuti haitaonekana kabisa. Endesha docker compose logs affine_migration ili kuona hatua iliyosimamisha mchakato. Sababu ya kawaida kwenye faili ya compose iliyohaririwa kwa mkono ni kutumia image ya kawaida ya postgres badala ya pgvector/pgvector:pg16, kwa sababu schema ya AFFiNE inatangaza extension ya pgvector na kuunda majedwali yenye safu za vector(1024) ambazo Postgres ya kawaida haiwezi kutengeneza.
AFFiNE inayojiendesha yenyewe inahitaji kiasi gani cha RAM?
Ukurasa wa mahitaji ya AFFiNE unaomba angalau CPU cores 4 na 2 GB ya RAM, ikipanda hadi 4 GB hati zinapozidi maneno 10,000, na inabainisha kuwa kuunganisha hati yenye marekebisho 10,000 kunaweza kufikia kilele cha 1 GB. Kwenye seva ya 2 GB, kilele hicho ndicho kinachokuangusha, si mzigo wa kawaida: kernel out-of-memory killer husimamisha mchakato wa AFFiNE, na restart: unless-stopped huuanzisha tena, kwa hivyo watumiaji huona ukurasa ukipakia upya badala ya error. Thibitisha hili kwa docker inspect affine_server --format '{{.State.OOMKilled}}' na sudo dmesg -T | grep -i 'out of memory', kisha ongeza swap file ya 2 GB ili ongezeko la ghafla liwe la polepole badala ya kuwa mbaya.
AFFiNE huhifadhi data yangu wapi, na nini ninachopaswa kuhifadhi (backup)?
Njia tatu chini ya saraka yako ya compose hushikilia kila kitu: ./data/postgres kwa database, ./data/storage kwa faili zilizopakiwa, na ./config kwa config.json. Hifadhi database kwa docker compose exec -T postgres pg_dump --format c --username affine affine > affine.dump badala ya kunakili faili, kwa sababu Postgres inayofanya kazi haiwezi kunakiliwa kwa usalama. Fanya tar ya ./data/storage kwa faili zilizopakiwa na uweke nakala ya config.json kwa mkono, kwa kuwa usafirishaji wa usanidi kutoka kwenye paneli ya admin umeorodheshwa kama haujatekelezwa kufikia Agosti 2026.
Je, ushirikiano wa wakati halisi (real-time collaboration) hufanya kazi kwenye AFFiNE inayojiendesha yenyewe?
Ndiyo, na hakuna kinachohitaji kuwezeshwa kwa ajili hiyo. Sharti pekee ni reverse proxy yako, kwa sababu sync hufanya kazi kupitia miunganisho ya WebSocket. Kwenye nginx hiyo inamaanisha proxy_http_version 1.1 pamoja na vichwa vya Upgrade na Connection: upgrade, wakati Traefik na Caddy hupitisha miunganisho hiyo bila usanidi wa ziada. Dalili ya proxy isiyoboresha miunganisho hiyo ni workspace inayopakia na kuingia kawaida wakati marekebisho yaliyofanywa kwenye kivinjari kimoja hayaonekani kwenye kingine.
Je, ninaweza kuendesha AFFiNE na image ya kawaida ya Postgres?
Hapana. schema.prisma ya AFFiNE inatangaza extensions = [pgvector(map: "vector")] na kufafanua majedwali manne yenye safu ya embedding ya aina ya vector(1024), na kazi ya migration huunda majedwali hayo hata wakati vipengele vya AI vimezimwa. Tumia pgvector/pgvector:pg16, ambayo ni Postgres 16 yenye extension hiyo iliyojumuishwa. Ikiwa utaelekeza AFFiNE kwenye seva ya nje ya Postgres badala yake, sakinisha pgvector kwenye seva hiyo na uunde extension kwenye database lengwa kabla ya kuendesha migration.