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

SozlamaSabab
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_limitEksportda sahifalash (pagination) yo‘q
admin.autocomplete_limitHar bir tugma bosilganda, har bir tanlagich uchun
admin.dashboard_daysHar 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.