Menata konfigurasi aplikasi Flask dengan config classes, environment variables, instance folder untuk data runtime, dan penyimpanan secrets, serta menerapkan prinsip 12-factor untuk memisahkan lingkungan dev, testing, dan produksi.

Sejauh ini semua kode kita berjalan dengan default Flask: secret_key kosong, database belum ada, dan debug mode ditentukan manual. Saat aplikasi mulai serius, kalian butuh cara mengelola konfigurasi — nilai yang berbeda antara development, testing, dan produksi — tanpa mencampurnya dengan logika. Inilah topik episode 8: configuration & environments.
Kita akan menerapkan prinsip 12-factor app: konfigurasi dari environment variables, pemisahan dev/prod yang tegas, dan penanganan secrets yang aman.
Flask menyimpan semua pengaturan di objek app.config — kamus yang bisa diakses dari mana saja:
from flask import Flask, current_app
app = Flask(__name__)
app.config["SECRET_KEY"] = "dev-only-key"
app.config["DEBUG"] = True
# di dalam view atau helper:
@app.get("/debug")
def debug_info() -> str:
return f"Debug mode: {current_app.config['DEBUG']}"app.config juga menyediakan akses atribut (app.config.SECRET_KEY) dan pengaturan bawaan Flask seperti DEBUG, TESTING, SECRET_KEY, dan MAX_CONTENT_LENGTH. Nilai yang masuk dari environment secara otomatis tersedia — berikutnya kita merapikannya dengan config classes.
Pola paling umum adalah config classes — satu class per lingkungan, semuanya mewarisi class dasar:
import os
class BaseConfig:
SECRET_KEY = os.environ.get("SECRET_KEY", "dev-change-me")
SQLALCHEMY_TRACK_MODIFICATIONS = False
class DevelopmentConfig(BaseConfig):
DEBUG = True
SQLALCHEMY_DATABASE_URI = "sqlite:///dev.db"
class TestingConfig(BaseConfig):
TESTING = True
SQLALCHEMY_DATABASE_URI = "sqlite:///:memory:"
class ProductionConfig(BaseConfig):
DEBUG = False
SECRET_KEY = os.environ["SECRET_KEY"] # wajib ada di produksi
SQLALCHEMY_DATABASE_URI = os.environ.get("DATABASE_URL")Pola ini memberi satu tempat untuk semua perbedaan lingkungan, dan nilai sensitif (SECRET_KEY, DATABASE_URL) diambil dari environment — bukan diketik di source code. Perhatikan TestingConfig memakai database in-memory agar test cepat dan terisolasi.
Muat class yang sesuai dengan environment yang aktif:
import os
from flask import Flask
from config import DevelopmentConfig, ProductionConfig, TestingConfig
def create_app() -> Flask:
app = Flask(__name__)
env = os.environ.get("FLASK_ENV", "development")
if env == "testing":
app.config.from_object(TestingConfig)
elif env == "production":
app.config.from_object(ProductionConfig)
else:
app.config.from_object(DevelopmentConfig)
return appBersamaan dengan application factory (episode 9), pola ini membuat aplikasi deterministik: environment yang sama → konfigurasi yang sama. Nilai FLASK_ENV juga memberi tahu perintah flask apakah debug mode aktif, sehingga flask run otomatis berperilaku sesuai lingkungan.
Prinsip inti 12-factor: konfigurasi masuk lewat environment variables, bukan hardcode di kode. Praktik yang benar:
export FLASK_ENV=development
export SECRET_KEY=generated-random-string
export DATABASE_URL=sqlite:///dev.dbDari Python, baca dengan os.environ.get() — dengan default hanya untuk development. Untuk memudahkan development lokal, gunakan file .env dan library seperti python-dotenv (Flask CLI otomatis membacanya jika terpasang):
FLASK_ENV=development
SECRET_KEY=dev-only-secretImportant
Jangan pernah commit file .env, config.local.py, atau file berisi secret ke git. Tambahkan ke .gitignore sejak awal, dan sediakan .env.example yang berisi placeholder agar anggota tim tahu variabel apa yang dibutuhkan. Secret di produksi sebaiknya disuntikkan lewat secret manager/CI.
Kadang aplikasi butuh menyimpan file runtime — database SQLite, file upload, atau cache — di lokasi yang bukan bagian dari source code. Flask menyediakan instance folder: folder khusus yang dibuat saat aplikasi diinisialisasi.
app = Flask(__name__, instance_relative_config=True)
# SQLite database di instance folder:
app.config.from_mapping(
SQLALCHEMY_DATABASE_URI=f"sqlite:///{app.instance_path}/app.db"
)
os.makedirs(app.instance_path, exist_ok=True)instance_relative_config=True membuat konfigurasi relatif terhadap instance folder — pas untuk file config lokal yang spesifik mesin (seperti config.cfg yang tidak di-commit). File di instance folder tidak ikut versioning dan tidak akan tertimpa saat deploy.
Secret adalah nilai yang wajib dijaga — SECRET_KEY, credential database, API key. Aturannya:
dev-only-key), boleh via .env.class ProductionConfig(BaseConfig):
SECRET_KEY = os.environ["SECRET_KEY"] # KeyError jika tidak ada
DATABASE_URL = os.environ["DATABASE_URL"]Dengan pola os.environ["..."] (tanpa default) di config produksi, aplikasi gagal cepat jika secret belum disuntikkan — lebih baik error saat start daripada aplikasi berjalan dengan secret default yang bisa ditebak.
Warning
SECRET_KEY default Flask yang "secret" sebenarnya sering dipakai aplikasi yang lupa mengubahnya — nilai default yang dikenal publik. Jika kalian memakai session cookie atau token (episode 13), secret key yang lemah berarti penyerang bisa memalsukan session. Selalu generate key acak panjang: python -c "import secrets; print(secrets.token_hex(32))".
config.py dengan class per lingkungan..env atau hardcode SECRET_KEY = pintu masuk penyerang.DEBUG=True di produksi = eksekusi kode remote via debugger (episode 3).DEBUG=False dan SECRET_KEY=None bisa disetel, tetapi dokumentasi eksplisit jauh lebih baik.Pada episode 8 ini, kalian telah menata konfigurasi ala 12-factor.
Inti yang harus dibawa pulang:
app.config adalah pusat konfigurasi Flask; akses lewat current_app.config.Base/Development/Testing/Production) memisahkan lingkungan dengan jelas..env hanya untuk development.os.environ["KEY"] tanpa default.Di episode 9 selanjutnya, kita merakit semuanya: blueprints & application factory — modular apps dengan url prefix dan blueprint-specific templates/static, create_app(), init extension, dan struktur proyek scalable untuk aplikasi sungguhan. Sampai jumpa di episode 9!