Deploy
Nimani sozlash kerak, nimani tekshirish kerak va proksi orqasida odamlar ko‘pincha yo‘l qo‘yadigan ikkita xato.
Mavjud v0.1.0
Muhit
Har qanday sozlamani muhit o‘zgaruvchisi orqali berish mumkin: FASTFORT_
prefiksi, ichma-ichlik uchun qo‘sh pastki chiziq.
FASTFORT_SECRET_KEY=… # from `fastfort generate-secret`
FASTFORT_DEBUG=false
FASTFORT_SECURITY__COOKIE_SECURE=true
FASTFORT_SECURITY__HSTS_SECONDS=31536000
FASTFORT_SECURITY__CSRF_ENABLED=true
FASTFORT_ADMIN__COUNT_STRATEGY=capped # on a large table
FASTFORT_ADMIN__COUNT_CAP=10000
FASTFORT_ADMIN__EXPORT_LIMIT=50000
FASTFORT_UI__ENVIRONMENT_LABEL=PRODUCTION
FASTFORT_UI__ENVIRONMENT_TONE=danger
Har bir guruhda extra="forbid" o‘rnatilgan, shuning uchun kalitdagi xato
ishga tushishda xatolikka olib keladi, aksincha jim-jit hech narsa qilmaydigan
sozlama bo‘lib qolmaydi.
Deployni tekshiruvga bog‘lang
uv run fastfort check --app main:fort --deploy
Nolga teng bo‘lmagan kod bilan tugaydi. U debug=True holatini, xavfsiz
bo‘lmagan cookie’ni, JavaScript o‘qiy oladigan cookie’ni, o‘chirilgan CSRF
himoyasini, o‘chirilgan xavfsizlik sarlavhalarini, bir soatdan uzoq
access-token muddatini va o‘chirilgan refresh-token rotatsiyasini xabar
qiladi.
- run: uv run fastfort check --app main:fort --deploy
env:
FASTFORT_SECRET_KEY: ${{ secrets.FASTFORT_SECRET_KEY }}
FASTFORT_DEBUG: "false"
FASTFORT_SECURITY__COOKIE_SECURE: "true"
Yoki ishga tushishning o‘zi rad etsin:
settings.require_production_ready()
Proksi orqasida odamlar ko‘pincha yo‘l qo‘yadigan ikki xato
trust_forwarded_for
FASTFORT_SECURITY__TRUST_FORWARDED_FOR=true
Buni faqat proksingiz X-Forwarded-Forni qayta yozadigan bo‘lsa yoqing.
Qo‘shib yozadigan proksi ortida yoki proksisiz mijoz o‘z manzilini
soxtalashtirishi mumkin — va lockout hamda audit yozuvlari tajovuzkor
tanlagan har qanday shaxsga tegishli bo‘lib qoladi.
HTML’ni siqmang
Statik fayllar FastFort tomonidan Brotli → gzip → identity tartibida allaqachon kelishiladi va har bir kodlash jarayon darajasida keshlanadi. HTML esa ataylab bundan chetlab o‘tilgan, chunki sahifada bir vaqtning o‘zida CSRF token va so‘rovga qarab tanlangan matn bor — bu BREACH hujum namunasi.
Shuning uchun: GZipMiddleware ishlatmang, va admin yo‘llari uchun proksida
HTML siqishni o‘chiring.
location /admin {
gzip off;
proxy_pass http://app;
proxy_set_header X-Forwarded-For $remote_addr; # overwrite, not append
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
}
Caddy’da «HTML’dan boshqa hamma narsa» deyishning imkoni yo‘q — uning javob
moslashtiruvchisida (matcher) not mavjud emas — shuning uchun ro‘yxat
teskari emas, balki ijobiy tarzda tuziladi:
encode {
zstd
gzip
match {
header Content-Type application/json*
header Content-Type text/csv*
}
}
Bu, aslida, yaxshiroq yondashuv: hali hech kim o‘ylab ko‘rmagan kontent turi siqilmagan holda keladi va e’tiborga olinadi, buning o‘rniga uni taqiqlar ro‘yxatiga qo‘shishni kimdir unutgani uchun siqilib ketavermaydi.
CDN’ni ham proksi deb hisoblang
Aynan shu narsa ko‘pincha e’tibordan chetda qoladi, va buni alohida
ta’kidlash kerak, chunki shu loyihaning o‘zining demo versiyasi ham bu xato
bilan chiqarilgan edi. Origin server HTML’ga tegmaydigan qilib tuzatildi,
deploy muvaffaqiyatli o‘tdi, ammo /admin/login baribir quyidagini
qaytarishda davom etdi:
content-encoding: zstd
server: cloudflare
Cloudflare, Fastly, CloudFront va boshqa har qanday CDN o‘z edge tugunlarida HTML’ni sukut bo‘yicha siqadi va TLS’ni ham o‘zlari tugatadi — shuning uchun mijozga baribir siqilgan uzunlik yetib boradi, BREACH esa siqishni qaysi mashina bajarganiga umuman qiziqmaydi. Faqat origin serverni tuzatib, shu bilan to‘xtash hech narsani tuzatmaydi.
Cloudflare’da bu Rules → Compression Rules bo‘limi: admin yo‘lini moslang va siqishni o‘chiring. Foydalanishga arzigulik har qanday CDN’da shunga o‘xshash imkoniyat bor; muhimi — sizda ikkita proksi borligini va faqat bittasini tuzatganingizni yodda tutish.
Tekshirish bitta so‘rov bilan amalga oshiriladi, va aniqlashning yagona yo‘li ham shu:
curl -sI -H 'Accept-Encoding: gzip, br, zstd' https://example.com/admin/login \
| grep -i content-encoding
Hech qanday natija chiqmasligi — to‘g‘ri natijadir.
Debug rejimi va resurslarni keshlash
debug=False bo‘lganda CSS va JavaScript diskdan bir marta o‘qiladi va
jarayon darajasida keshlanadi. Productionda aynan shu kerak, va bu stildagi
o‘zgartirish uchun qayta ishga tushirish talab etilishini anglatadi.
debug=True bo‘lganda esa ular har bir so‘rovda qayta o‘qiladi — bu sozlama
aynan shuning uchun mavjud, va aynan shuning uchun u productionda yoqilgan
bo‘lmasligi kerak.
Docker
FROM python:3.13-slim
# uv, then dependencies, then source — so a source change does not re-resolve.
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev
COPY . .
# No `npm install`, no node_modules, no build step. The admin's CSS and
# JavaScript are files inside the wheel.
ENV FASTFORT_DEBUG=false
EXPOSE 8000
CMD ["uv", "run", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
Migratsiyalar
FastFort hech qachon DDL bajarmaydi. Sxema — bu sizning mas’uliyatingiz: Alembic yoki siz allaqachon foydalanayotgan boshqa vosita. Modellar — MRO’da FastFort bazaviy klassi bo‘lmagan oddiy deklarativ modellar, va aynan shu narsa buni mumkin qiladi.
Ma’lumotlar bazasi kengaytmalari bilan ham xuddi shunday: postgis,
hstore, citext va vector har biri o‘z turini qo‘shadi, shuning uchun
ulardan birini nomlagan CREATE TABLE DDL darajasida ishlamay qoladi,
agar kengaytma yoqilmagan bo‘lsa. Ularni yoqish — sizning loyihangiz
vazifasi: ma’lumotlar bazasi kengaytmalarini jim-jit o‘rnatadigan admin
freymvorkini hech kim ko‘rib chiqa olmaydi.
Birinchi hisob
FF_PASSWORD="$(openssl rand -base64 24)" \
uv run fastfort createsuperuser \
--app app.main:fort \
--identity ops@example.com \
--password-env FF_PASSWORD \
--no-input
--password-env, --password emas: argument jarayonlar ro‘yxatida
(process list) ko‘rinib turadi.
Yuklama uchun sozlamalar
| Sozlama | Sabab |
|---|---|
admin.count_strategy = "capped" | Aniq hisoblash bir necha yuz mingdan ortiq qatorlarda so‘rov vaqtini egallab oladi |
admin.max_page_size | ?ps= uchun yuqori chegara; usiz bitta so‘rov butun jadvalni talab qilishi mumkin |
admin.export_limit | Eksportda sahifalash (pagination) yo‘q |
admin.autocomplete_limit | Har bir tugma bosilganda, har bir tanlagich uchun |
admin.dashboard_days | Har bir kun bitta indekslangan hisoblashni bildiradi, shuning uchun bu son dashboard so‘rovlari sonini ham belgilaydi |
Standart paketda yo‘q narsalar
So‘rovlar chastotasini cheklash (rate limiting), audit-log backend va soft
delete fastfort.contribda rejalashtirilgan, lekin hali u yerda yo‘q.
Ayniqsa so‘rovlar chastotasini cheklashni bugunoq proksi yoki gateway
darajasida joylashtirish kerak — lockout_* faqat login formasini himoya
qiladi, boshqa hech narsani emas.