Konfiguracja środowiska

Goat korzysta ze zmiennych środowiskowych do konfiguracji aplikacji, połączeń z bazą danych, katalogów roboczych oraz ustawień zależnych od konkretnego środowiska.

W lokalnym developmentcie wartości te są zazwyczaj przechowywane w pliku:

.env

Nazwy zmiennych używanych przez aplikację rozpoczynają się od prefiksu:

GOAT_

Plik .env powinien zawierać wyłącznie konfigurację właściwą dla lokalnego środowiska. Nie traktuj go jako miejsca do przechowywania sekretów produkcyjnych i nie umieszczaj prawdziwych haseł, tokenów ani kluczy w publicznym repozytorium.

Najważniejsze zmienne

ZmiennaZnaczenie
GOAT_DEVWłącza tryb deweloperski aplikacji.
GOAT_DB_MAIN_HOSTHost głównej bazy PostgreSQL.
GOAT_DB_MAIN_PORTPort głównej bazy PostgreSQL.
GOAT_DB_MAIN_USERUżytkownik głównej bazy.
GOAT_DB_MAIN_PASSHasło użytkownika głównej bazy.
GOAT_DB_MAIN_NAMENazwa głównej bazy danych.
GOAT_DB_TEST_HOSTHost bazy używanej przez testy.
GOAT_DB_TEST_PORTPort bazy testowej.
GOAT_DB_TEST_USERUżytkownik bazy testowej.
GOAT_DB_TEST_PASSHasło użytkownika bazy testowej.
GOAT_DB_TEST_NAMENazwa bazy testowej.
GOAT_JWT_SECRETSekret używany do podpisywania tokenów JWT.
GOAT_URL_BASEPubliczny bazowy adres URL aplikacji.
GOAT_DIR_DATAKatalog danych aplikacji.
GOAT_DIR_TMPLokalny katalog plików tymczasowych.
GOAT_DIR_SHARED_TMPKatalog tymczasowy współdzielony pomiędzy procesami lub kontenerami.
GOAT_DOMAINDomena używana przez konfigurację środowiska docelowego.

Przykład lokalnej konfiguracji

Minimalna konfiguracja lokalnego środowiska może wyglądać następująco:

GOAT_DEV=TRUE

GOAT_DB_MAIN_HOST=localhost
GOAT_DB_MAIN_PORT=5433
GOAT_DB_MAIN_USER=admin
GOAT_DB_MAIN_PASS=local-password
GOAT_DB_MAIN_NAME=maindb

GOAT_JWT_SECRET=zmien-na-dlugi-losowy-sekret

GOAT_URL_BASE=http://localhost:8080/

Wartości z przykładu są przeznaczone wyłącznie do developmentu.

Dane dostępowe do środowisk współdzielonych, stagingowych i produkcyjnych powinny być dostarczane przez mechanizm konfiguracji właściwy dla danego środowiska.

Tryb deweloperski

Zmiennej:

GOAT_DEV

używaj do określenia, czy aplikacja działa w trybie developerskim.

Przykład:

GOAT_DEV=TRUE

Tryb deweloperski może wpływać na zachowanie aplikacji związane między innymi z:

  • logowaniem,
  • diagnostyką,
  • obsługą błędów,
  • cache,
  • narzędziami pomocniczymi,
  • sposobem uruchamiania frontendu lub backendu.

Nie zakładaj, że konfiguracja developerska jest odpowiednia dla środowiska produkcyjnego.

Konfiguracja głównej bazy danych

Główne połączenie z PostgreSQL jest określane przez zestaw zmiennych:

GOAT_DB_MAIN_HOST
GOAT_DB_MAIN_PORT
GOAT_DB_MAIN_USER
GOAT_DB_MAIN_PASS
GOAT_DB_MAIN_NAME

Przykład:

GOAT_DB_MAIN_HOST=localhost
GOAT_DB_MAIN_PORT=5433
GOAT_DB_MAIN_USER=admin
GOAT_DB_MAIN_PASS=local-password
GOAT_DB_MAIN_NAME=maindb

Te wartości są wykorzystywane przez aplikację oraz skrypty odpowiedzialne za pracę z główną bazą danych.

W lokalnym środowisku PostgreSQL jest domyślnie uruchamiany przez skrypty Goat w Dockerze.

Oddzielna baza dla testów

Testy mogą korzystać z osobnego połączenia:

GOAT_DB_TEST_HOST
GOAT_DB_TEST_PORT
GOAT_DB_TEST_USER
GOAT_DB_TEST_PASS
GOAT_DB_TEST_NAME

Oddzielenie bazy testowej od developerskiej zmniejsza ryzyko przypadkowego usunięcia lub modyfikacji danych używanych podczas codziennej pracy.

Przykładowa konfiguracja:

GOAT_DB_TEST_HOST=localhost
GOAT_DB_TEST_PORT=5433
GOAT_DB_TEST_USER=admin
GOAT_DB_TEST_PASS=local-password
GOAT_DB_TEST_NAME=testdb

Szczególnie ważne jest, aby destrukcyjne operacje wykonywane podczas testów nigdy nie wskazywały na bazę produkcyjną.

Sekret JWT

Zmiennej:

GOAT_JWT_SECRET

aplikacja używa do podpisywania tokenów JWT.

Wartość powinna być:

  • długa,
  • losowa,
  • unikalna dla danego środowiska,
  • niedostępna publicznie.

Nie używaj przykładowego sekretu w środowisku produkcyjnym.

Nie zapisuj rzeczywistego GOAT_JWT_SECRET w plikach śledzonych przez Git.

Każde środowisko powinno posiadać własną wartość. W szczególności środowisko lokalne, testowe i produkcyjne nie powinny współdzielić tego samego sekretu.

Publiczny adres aplikacji

Zmiennej:

GOAT_URL_BASE

używaj do określenia publicznego bazowego adresu aplikacji.

Lokalnie może to być:

GOAT_URL_BASE=http://localhost:8080/

Na środowisku docelowym wartość powinna odpowiadać rzeczywistemu adresowi użytkowanemu przez klientów aplikacji.

Może być wykorzystywana między innymi podczas generowania:

  • odnośników absolutnych,
  • callbacków,
  • adresów w wiadomościach,
  • metadanych,
  • linków do zasobów aplikacji.

Katalogi danych i plików tymczasowych

Goat pozwala skonfigurować lokalizacje wykorzystywane do przechowywania danych oraz plików tymczasowych.

Służą do tego:

GOAT_DIR_DATA
GOAT_DIR_TMP
GOAT_DIR_SHARED_TMP

GOAT_DIR_DATA wskazuje katalog przeznaczony na dane aplikacji.

GOAT_DIR_TMP może być używany przez pojedynczy proces do przechowywania plików tymczasowych.

GOAT_DIR_SHARED_TMP jest przeznaczony dla danych tymczasowych, które muszą być dostępne dla więcej niż jednego procesu lub kontenera.

Jawne definiowanie tych katalogów ułatwia dostosowanie aplikacji do różnych środowisk uruchomieniowych.

Domena środowiska

Zmiennej:

GOAT_DOMAIN

można używać do określenia domeny związanej z aktualnym środowiskiem.

Wartość może być wykorzystywana przez konfigurację wdrożeniową, reverse proxy, generowanie adresów lub inne elementy infrastruktury.

Przykładowo:

GOAT_DOMAIN=example.com

Nie należy utożsamiać jej automatycznie z GOAT_URL_BASE.

GOAT_DOMAIN opisuje domenę, natomiast GOAT_URL_BASE może zawierać pełny adres wraz z protokołem, portem i ścieżką bazową.

Sekrety i kontrola wersji

Pliki konfiguracyjne przechowywane w repozytorium powinny zawierać jedynie bezpieczne wartości przykładowe.

Rzeczywiste sekrety przechowuj poza kontrolą wersji.

Dotyczy to przede wszystkim:

GOAT_DB_MAIN_PASS
GOAT_DB_TEST_PASS
GOAT_JWT_SECRET

W lokalnym środowisku mogą znajdować się w .env.

Na środowiskach współdzielonych i produkcyjnych lepiej dostarczać je przez:

  • zmienne środowiskowe platformy,
  • system CI/CD,
  • manager sekretów,
  • mechanizmy udostępniane przez platformę wdrożeniową.

Dobrą praktyką jest przechowywanie w repozytorium pliku przykładowego, np.:

.env.example

zawierającego nazwy wymaganych zmiennych, ale bez rzeczywistych sekretów.

Przykład:

GOAT_DEV=TRUE

GOAT_DB_MAIN_HOST=localhost
GOAT_DB_MAIN_PORT=5433
GOAT_DB_MAIN_USER=
GOAT_DB_MAIN_PASS=
GOAT_DB_MAIN_NAME=

GOAT_JWT_SECRET=

GOAT_URL_BASE=http://localhost:8080/

Taki plik ułatwia przygotowanie nowego środowiska bez ujawniania poufnych danych.

Konfiguracja kontenerów

Lokalne skrypty Goat wykorzystują Docker do uruchamiania części infrastruktury projektu.

W szczególności skrypty bazodanowe uruchamiają PostgreSQL w kontenerze i udostępniają go lokalnie na porcie:

5433

Z punktu widzenia procesu uruchamianego bezpośrednio na hoście połączenie może więc wyglądać tak:

GOAT_DB_MAIN_HOST=localhost
GOAT_DB_MAIN_PORT=5433

Sytuacja wygląda inaczej, gdy sama aplikacja działa wewnątrz kontenera.

Dla procesu wewnątrz Dockera:

localhost

oznacza jego własny kontener, a nie system hosta.

Dlatego skrypt developerski może nadpisać host bazy na:

host.docker.internal

Przepływ wygląda wtedy w uproszczeniu tak:

aplikacja w kontenerze
        ↓
host.docker.internal:5433
        ↓
port wystawiony przez hosta
        ↓
PostgreSQL

Pozwala to korzystać z tej samej konfiguracji projektu niezależnie od tego, czy dane polecenie jest wykonywane bezpośrednio na hoście, czy wewnątrz kontenera.

Konfiguracja lokalna a konfiguracja docelowa

Nie warto kopiować lokalnego .env bez zmian na serwer.

Lokalnie konfiguracja jest zoptymalizowana pod wygodę developmentu:

localhost
porty wystawione przez Docker
GOAT_DEV=TRUE
lokalne hasła
lokalne katalogi

Środowisko produkcyjne może natomiast korzystać z:

wewnętrznego hosta PostgreSQL
sekretów dostarczanych przez platformę
HTTPS
trwałych wolumenów
innych katalogów danych
GOAT_DEV=FALSE

Konfiguracja powinna więc być traktowana jako element zależny od środowiska, a nie część kodu aplikacji.

Typowy workflow lokalny

Przygotowanie lokalnej konfiguracji może wyglądać następująco:

cp .env.example .env

Następnie uzupełnij wartości wymagane przez projekt:

GOAT_DEV=TRUE

GOAT_DB_MAIN_HOST=localhost
GOAT_DB_MAIN_PORT=5433
GOAT_DB_MAIN_USER=admin
GOAT_DB_MAIN_PASS=local-password
GOAT_DB_MAIN_NAME=maindb

GOAT_JWT_SECRET=lokalny-losowy-sekret

GOAT_URL_BASE=http://localhost:8080/

Po zapisaniu konfiguracji możesz uruchomić środowisko:

goat run:script --path=herd/dev.goat

Skrypty Goat przygotują pozostałe elementy środowiska zgodnie z konfiguracją projektu.

Najważniejsza zasada

Kod aplikacji powinien określać jakiej konfiguracji potrzebuje, natomiast konkretne wartości powinny pochodzić ze środowiska, w którym aplikacja jest uruchamiana.

Dzięki temu ten sam kod może działać lokalnie, w testach, CI, na stagingu i produkcji bez konieczności wprowadzania zmian bezpośrednio w źródłach.

Sekrety traktuj jako dane środowiska, nie jako część projektu.