- Real-time updates (Laravel Reverb): live operator queue, live ticket chat/detail updates for operator and client, periodic fallback refresh with a visible countdown as a backstop for dropped websocket connections. - SLA automation rules (Admin > Automatyzacja SLA): act on a ticket after N minutes of customer silence (change priority/status/team/assignee), evaluated every 15 minutes, reusing TicketService's own setters so automated changes get the same history/notification/broadcast a manual change would. - New notification: every operator on a matching team gets notified when a new ticket lands in one of their subcategories. - BookStack knowledge-base sidebar now also shown on the client's own ticket view (previously operator-only); suggestions everywhere now load in after first paint instead of blocking it. - Client ticket view: shows assigned operator + team; page widened to match the operator's. - Notification bell shows unread only; read notifications disappear instead of just dimming. - Stats dashboard: sectioned layout, new breakdowns (by subcategory, CSAT by team/operator, top clients, client x subcategory cross-tab). - Mobile: nav dropdowns (theme/notifications/profile) now expand full width instead of overflowing off-screen below 640px. - Fixed two bugs that silently disabled all real-time updates (missing CSRF header on Echo's private-channel auth; a script-load-order race that could miss the livewire:init event) and the mariadb healthcheck (world-writable credentials file on this stack's NFS mount). - Assorted test-suite fixes (roles virtual attribute needs the roles table seeded; a few missing seeds/wrong assertions found along the way). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
522 lines
18 KiB
Markdown
522 lines
18 KiB
Markdown
# Instalacja / wdrożenie
|
|
|
|
Dwa sposoby uruchomienia Servicedesk: przez **Docker Compose** (tak jak działa ten
|
|
projekt obecnie) albo **bezpośrednio na serwerze** z Apache/Nginx + PHP-FPM, bez
|
|
kontenerów.
|
|
|
|
Zanim zaczniesz, ważne rozróżnienie — w projekcie są **dwa różne pliki `.env`**:
|
|
|
|
| Plik | Do czego służy |
|
|
|---|---|
|
|
| `.env` (w katalogu głównym repo, obok `compose.yaml`) | Zmienne dla **Docker Compose** — hasła do MariaDB, nazwa hosta dla Traefika. Czyta go `compose.yaml`, **nie** czyta go Laravel. |
|
|
| `src/.env` (w katalogu aplikacji Laravel) | Cała konfiguracja **aplikacji** — połączenie z bazą, adres URL, klucz szyfrowania, LDAP, SMTP, itd. Czyta go wyłącznie Laravel. |
|
|
|
|
Oba istnieją niezależnie od siebie (nawet w wersji Docker) — wartości `DB_*` w
|
|
`src/.env` muszą **odpowiadać** wartościom `MYSQL_*` z głównego `.env`, ale to dwa
|
|
osobne pliki, w dwóch różnych miejscach.
|
|
|
|
---
|
|
|
|
## 1. Wdrożenie przez Docker Compose
|
|
|
|
### Wymagania
|
|
|
|
- Docker + wtyczka `docker compose`.
|
|
- Zewnętrzna sieć Docker `traefik_public`, jeśli używasz Traefika tak jak w
|
|
`compose.yaml` (`docker network create traefik_public`, jeśli jeszcze nie
|
|
istnieje). Bez Traefika trzeba samodzielnie zmapować porty serwisu `servicedesk`
|
|
na hosta (`ports: ["8080:80"]`) i obsłużyć TLS inaczej (patrz sekcja 2 niżej, w
|
|
razie potrzeby reverse-proxy przed kontenerem).
|
|
|
|
### 1.1. Pliki `compose.yaml` i `.env` w katalogu głównym
|
|
|
|
Oba są celowo `.gitignore`'owane (podobnie jak `src/.env`) — kopiujesz je z
|
|
szablonów przy pierwszym wdrożeniu, a potem edytujesz lokalnie:
|
|
|
|
```bash
|
|
cp compose.yaml.example compose.yaml
|
|
cp .env.example .env
|
|
```
|
|
|
|
`.env`:
|
|
|
|
```env
|
|
HOSTNAME=servicedesk.twoja-domena.pl
|
|
MYSQL_ROOT_PASSWORD=wygeneruj-silne-haslo
|
|
MYSQL_DATABASE=servicedesk
|
|
MYSQL_USER=servicedesk
|
|
MYSQL_PASSWORD=wygeneruj-inne-silne-haslo
|
|
# IMAGE_TAG=latest
|
|
```
|
|
|
|
- `HOSTNAME` — domena, pod którą Traefik wystawi aplikację (trafia do reguły
|
|
`Host(...)` w etykietach `servicedesk`).
|
|
- `MYSQL_*` — dane bazy dla kontenera `mariadb`; `MYSQL_USER`/`MYSQL_PASSWORD` to
|
|
**te same** wartości, które za chwilę wpiszesz do `src/.env` jako `DB_USERNAME`/
|
|
`DB_PASSWORD`.
|
|
- `IMAGE_TAG` — który tag obrazu `servicedesk` wdrożyć (patrz sekcja 1.3a); domyślnie
|
|
`latest`, jeśli zmienna nie jest ustawiona.
|
|
|
|
### 1.2. Plik `src/.env` (Laravel)
|
|
|
|
```bash
|
|
cp src/.env.example src/.env
|
|
```
|
|
|
|
Kluczowe wartości do zmiany względem `.env.example`:
|
|
|
|
```env
|
|
APP_NAME=Servicedesk
|
|
APP_ENV=production
|
|
APP_DEBUG=false
|
|
APP_URL=https://servicedesk.twoja-domena.pl # to samo co HOSTNAME wyżej, z https://
|
|
APP_LOCALE=pl
|
|
APP_FALLBACK_LOCALE=pl
|
|
|
|
AUTHOR_CONTACT=helpdesk@twoja-domena.pl # widoczne w Admin > O aplikacji
|
|
VERSION=1.1.2 # widoczne w Admin > O aplikacji
|
|
|
|
DB_CONNECTION=mysql
|
|
DB_HOST=mariadb # nazwa serwisu z compose.yaml, NIE 127.0.0.1
|
|
DB_PORT=3306
|
|
DB_DATABASE=servicedesk # = MYSQL_DATABASE z głównego .env
|
|
DB_USERNAME=servicedesk # = MYSQL_USER
|
|
DB_PASSWORD=wygeneruj-inne-silne-haslo # = MYSQL_PASSWORD
|
|
|
|
SESSION_DRIVER=database
|
|
QUEUE_CONNECTION=database
|
|
```
|
|
|
|
`APP_KEY` wygenerujesz komendą artisan (krok 1.4) — zostaw puste w pliku.
|
|
|
|
`LDAP_*` i `MAIL_*` w `src/.env` są tylko **wartościami startowymi/awaryjnymi**.
|
|
Docelowo LDAP i SMTP konfiguruje się wygodniej z poziomu **Admin > Konfiguracja**
|
|
w samej aplikacji (patrz ramka ostrzegawcza w kroku 1.6) — ale jeśli chcesz mieć
|
|
sensowny fallback zanim ktokolwiek się zaloguje do panelu admina, warto je od razu
|
|
uzupełnić:
|
|
|
|
```env
|
|
LDAP_HOST=ldap.twoja-domena.pl
|
|
LDAP_USERNAME=cn=admin,dc=twoja-domena,dc=pl
|
|
LDAP_PASSWORD=haslo-bind-ldap
|
|
LDAP_BASE_DN=dc=twoja-domena,dc=pl
|
|
LDAP_PORT=389
|
|
|
|
MAIL_MAILER=smtp
|
|
MAIL_HOST=smtp.twoja-domena.pl
|
|
MAIL_PORT=587
|
|
MAIL_USERNAME=noreply@twoja-domena.pl
|
|
MAIL_PASSWORD=haslo-smtp
|
|
MAIL_FROM_ADDRESS=noreply@twoja-domena.pl
|
|
MAIL_FROM_NAME="${APP_NAME}"
|
|
```
|
|
|
|
### 1.3. Start kontenerów
|
|
|
|
Obraz `servicedesk` **nie jest budowany lokalnie** — `compose.yaml` odwołuje się
|
|
do obrazu zbudowanego przez CI i wypchniętego do rejestru kontenerów Gitea (patrz
|
|
1.3a). Uruchomienie stacka to więc zawsze:
|
|
|
|
```bash
|
|
docker compose pull
|
|
docker compose up -d
|
|
```
|
|
|
|
Przy zwykłych zmianach w kodzie PHP/Blade nic więcej nie trzeba robić — źródło
|
|
jest zamontowane z `./src`, Laravel odświeża się natychmiast. `docker compose
|
|
pull` uruchamiaj ponownie tylko wtedy, gdy chcesz podnieść nowszy tag obrazu
|
|
(np. po zmianie w `Dockerfile` i przebudowie przez CI).
|
|
|
|
### 1.3a. Automatyczne budowanie obrazu (CI, Gitea Actions)
|
|
|
|
`.gitea/workflows/build.yml` buduje i wypycha obraz do wbudowanego rejestru
|
|
kontenerów Gitea (`gitea.kzbikowski.pl/kzbkowski/servicedesk`) po każdym pushu na
|
|
`main`, który zmienia `Dockerfile` (celowo nie odpala się na zwykłe zmiany w
|
|
`src/` — obraz nie zawiera kodu aplikacji, tylko PHP/Apache/rozszerzenia, więc
|
|
przebudowa dla samego kodu byłaby marnowaniem czasu CI). Wypycha dwa tagi:
|
|
`latest` i `<sha commita>`.
|
|
|
|
Zanim to zadziała, workflow potrzebuje sekretu `REGISTRY_TOKEN` — Gitei **nie**
|
|
ufaj domyślnemu `secrets.GITHUB_TOKEN` do logowania w jej własnym rejestrze
|
|
kontenerów, w praktyce kończy się to błędem `unauthorized` przy
|
|
`docker login`. Zamiast tego:
|
|
|
|
1. Wygeneruj token: **Ustawienia użytkownika > Aplikacje > Generate New Token**,
|
|
z uprawnieniami co najmniej `write:package` i `read:package`.
|
|
2. Dodaj go jako sekret repo: **Ustawienia repo > Actions > Secrets** →
|
|
nazwa `REGISTRY_TOKEN`, wartość = wygenerowany token.
|
|
|
|
Jeśli ten sekret nie jest ustawiony, workflow celowo przerywa się **przed**
|
|
próbą logowania z czytelnym komunikatem błędu (`::error::`), zamiast wysyłać
|
|
puste/nieautoryzowane dane do rejestru i kończyć na niejasnym `unauthorized` z
|
|
demona Dockera.
|
|
|
|
To **tylko build + push** — świadomie bez auto-deployu na produkcję. Po tym jak
|
|
CI skończy, wdrożenie nowego obrazu na serwerze wciąż jest ręcznym krokiem:
|
|
|
|
```bash
|
|
cd /ścieżka/do/repo
|
|
docker compose pull
|
|
docker compose up -d
|
|
```
|
|
|
|
Zanim to zadziała po raz pierwszy, potrzebne jest jednorazowe zalogowanie hosta
|
|
produkcyjnego do rejestru Gitea (żeby `docker compose pull` miał czym
|
|
autoryzować pobranie obrazu, jeśli repozytorium/paczka nie są publiczne):
|
|
|
|
```bash
|
|
docker login gitea.kzbikowski.pl -u <twoja-nazwa-uzytkownika>
|
|
```
|
|
|
|
Jeśli to zupełnie pierwsze wdrożenie (rejestr jeszcze nie ma żadnego wypchniętego
|
|
obrazu `servicedesk`) — poczekaj, aż workflow CI przejdzie choć raz (np. przez
|
|
push/PR zmieniający `Dockerfile`, albo ręczne odpalenie z zakładki Actions w
|
|
Gitea), zanim spróbujesz `docker compose pull` na serwerze.
|
|
|
|
### 1.3b. Real-time (Laravel Reverb)
|
|
|
|
Realtime (kolejka operatora, czat na żywo) wymaga trzeciej usługi w
|
|
`compose.yaml`, `reverb` — tego samego obrazu `servicedesk`, tylko z innym
|
|
`command: php artisan reverb:start --host=0.0.0.0 --port=8080`. Obraz musi
|
|
mieć rozszerzenia PHP `pcntl`/`posix` (potrzebne serwerowi Reverb do obsługi
|
|
sygnałów) — jeśli `Dockerfile` ich nie instaluje, `reverb` będzie się zapętlać
|
|
w restartach z błędem `Undefined constant "...SIGINT"`; dodaj `pcntl posix` do
|
|
listy w `docker-php-ext-install` i poczekaj na przebudowanie obrazu przez CI.
|
|
|
|
Traefik musi kierować ścieżkę websocketu (`/app*`) do `reverb`, a resztę do
|
|
`servicedesk` — na tej samej domenie, więc bez dodatkowego wpisu DNS/certyfikatu:
|
|
|
|
```yaml
|
|
reverb:
|
|
image: gitea.kzbikowski.pl/kzbkowski/servicedesk:${IMAGE_TAG:-latest}
|
|
command: php artisan reverb:start --host=0.0.0.0 --port=8080
|
|
volumes:
|
|
- ./src:/var/www/html
|
|
restart: unless-stopped
|
|
depends_on:
|
|
mariadb:
|
|
condition: service_healthy
|
|
networks:
|
|
- internal
|
|
- traefik_public
|
|
labels:
|
|
- traefik.enable=true
|
|
- traefik.docker.network=traefik_public
|
|
- traefik.http.routers.reverb.rule=Host(`${HOSTNAME}`) && PathPrefix(`/app`)
|
|
- traefik.http.routers.reverb.priority=1000
|
|
- traefik.http.routers.reverb.entrypoints=websecure
|
|
- traefik.http.routers.reverb.tls=true
|
|
- traefik.http.services.reverb.loadbalancer.server.port=8080
|
|
```
|
|
|
|
`priority=1000` jest ważne — Traefik domyślnie liczy priorytet reguły na
|
|
podstawie długości jej zapisu, co może dać samemu `Host(...)` z `servicedesk`
|
|
wyższy priorytet niż oczekiwano, przez co ścieżkowa reguła `reverb` przegrywa i
|
|
nic nie działa mimo poprawnej konfiguracji.
|
|
|
|
W `src/.env` — `BROADCAST_CONNECTION=reverb` plus:
|
|
|
|
```env
|
|
REVERB_APP_ID=wygeneruj-losowy-id
|
|
REVERB_APP_KEY=wygeneruj-losowy-klucz
|
|
REVERB_APP_SECRET=wygeneruj-losowy-sekret
|
|
REVERB_HOST=reverb # nazwa usługi compose — ruch serwer-serwer po sieci internal
|
|
REVERB_PORT=8080
|
|
REVERB_SCHEME=http
|
|
|
|
VITE_REVERB_APP_KEY="${REVERB_APP_KEY}"
|
|
VITE_REVERB_HOST=servicedesk.twoja-domena.pl # publiczna domena — to, z czym łączy się przeglądarka
|
|
VITE_REVERB_PORT=443
|
|
VITE_REVERB_SCHEME=https
|
|
```
|
|
|
|
`REVERB_HOST` (serwer→serwer, wewnętrzna sieć Docker) i `VITE_REVERB_HOST`
|
|
(przeglądarka→Traefik, publiczna domena) to celowo dwie różne wartości —
|
|
pomylenie ich to najczęstszy błąd przy pierwszym wdrożeniu tej funkcji.
|
|
|
|
Po zmianie zmiennych `VITE_REVERB_*` trzeba przebudować front-end (krok 1.5) —
|
|
te wartości są wypiekane w zbudowany bundle JS, nie czytane w runtime.
|
|
|
|
### 1.4. Instalacja aplikacji wewnątrz kontenera
|
|
|
|
```bash
|
|
docker compose exec servicedesk composer install --no-dev --optimize-autoloader
|
|
docker compose exec servicedesk php artisan key:generate
|
|
docker compose exec servicedesk php artisan migrate --seed
|
|
docker compose exec servicedesk php artisan storage:link
|
|
```
|
|
|
|
`migrate --seed` (bez `--fresh`) na pustej bazie utworzy wszystkie tabele i
|
|
wypełni dane referencyjne: kategorie/podkategorie, pola dodatkowe, statusy,
|
|
priorytety/SLA, zespoły, szybkie akcje, szablony odpowiedzi/e-mail, branding oraz
|
|
**jedno konto lokalne `admin@example.com` / `admin`** — zmień jego hasło od razu
|
|
po pierwszym zalogowaniu (Admin > Użytkownicy).
|
|
|
|
### 1.5. Zbudowanie zasobów front-endowych (CSS/Tailwind)
|
|
|
|
Ani host, ani kontener `servicedesk` nie mają zainstalowanego Node.js — buduj
|
|
przez jednorazowy kontener `node:22` zamiast dorzucać Node do obrazu aplikacji:
|
|
|
|
```bash
|
|
cd /ścieżka/do/repo
|
|
docker run --rm -v "$(pwd)/src":/app -w /app node:22 npm ci
|
|
docker run --rm -v "$(pwd)/src":/app -w /app node:22 npm run build
|
|
```
|
|
|
|
Powtarzaj drugi krok po każdej zmianie w `resources/css/` lub `resources/js/`.
|
|
|
|
### 1.6. Zadanie cykliczne (SLA) i kolejka
|
|
|
|
`routes/console.php` planuje `tickets:check-sla-breaches` co 15 minut, ale **obraz
|
|
Dockera nie ma wbudowanego cron/supervisora** — bez dodatkowego kroku to zadanie
|
|
nigdy się nie uruchomi. Najprościej dodać wpis crona **na hoście**:
|
|
|
|
```cron
|
|
* * * * * cd /ścieżka/do/repo && docker compose exec -T servicedesk php artisan schedule:run >> /dev/null 2>&1
|
|
```
|
|
|
|
Powiadomienia e-mail wysyłają się synchronicznie (nie trafiają do kolejki), więc
|
|
`php artisan queue:work` nie jest obowiązkowy — `QUEUE_CONNECTION=database` w
|
|
`.env` wystarcza jako bezpieczny domyślny driver, gdyby coś w przyszłości zaczęło
|
|
kolejkować zadania.
|
|
|
|
### ⚠️ Ważne: LDAP/SMTP z panelu Admina nadpisują `.env` w locie
|
|
|
|
`AppServiceProvider` na starcie żądania sprawdza tabelę `settings` — jeśli w
|
|
Admin > Konfiguracja pole **host LDAP** albo **SMTP włączony + host** jest
|
|
ustawione, **te wartości wygrywają z `.env`**, bez potrzeby restartu czy redeployu.
|
|
|
|
Po świeżym `migrate --seed` te pola zawierają **przykładowe placeholdery**
|
|
(`ldap.example.com`, `smtp.example.com`, `changeme-*-password`) — to znaczy, że
|
|
zaraz po instalacji LDAP/SMTP **faktycznie próbują łączyć się z tymi fałszywymi
|
|
adresami**, nawet jeśli w `.env` wpisałeś prawdziwe dane! Zanim oddasz system do
|
|
użytku:
|
|
|
|
1. Zaloguj się lokalnym kontem `admin@example.com` / `admin`.
|
|
2. Wejdź w **Admin > Konfiguracja** i wpisz prawdziwe dane LDAP/SMTP (albo wyczyść
|
|
pole hosta LDAP, żeby wrócić do wartości z `.env`).
|
|
3. Użyj przycisków **„Testuj połączenie”** przy obu sekcjach, zanim zaczniesz
|
|
polegać na logowaniu przez katalog.
|
|
|
|
### Integracje opcjonalne (BookStack)
|
|
|
|
Podpowiedzi artykułów z bazy wiedzy BookStack (przy tworzeniu zgłoszenia i w
|
|
panelu operatora) są **domyślnie wyłączone** i nie wymagają żadnej zmiennej w
|
|
`.env` — całość konfiguruje się w **Admin > Konfiguracja**: adres instancji,
|
|
Token ID/Secret (rola/użytkownik właściciela tokenu musi mieć w BookStacku
|
|
uprawnienie „Access System API”), oraz osobne listy dozwolonych półek dla
|
|
podpowiedzi przy tworzeniu zgłoszenia i dla panelu operatora — dopóki żadna
|
|
półka nie jest zaznaczona, wyszukiwanie nic nie zwraca.
|
|
|
|
---
|
|
|
|
## 2. Wdrożenie bezpośrednio na serwerze (Apache/Nginx, bez Dockera)
|
|
|
|
### Wymagania
|
|
|
|
- **PHP 8.3+** z rozszerzeniami: `curl`, `mysqli`, `pdo_mysql`, `ldap`, `zip`,
|
|
`mbstring`, `openssl`, `tokenizer`, `xml`, `ctype`, `bcmath`, `fileinfo`.
|
|
- **Composer 2**.
|
|
- **MariaDB/MySQL** (osobny serwer lub lokalny).
|
|
- **Node.js 20+** — tylko do jednorazowej (lub przy update'ach) budowy zasobów
|
|
Tailwind/Vite; niepotrzebny w runtime.
|
|
- **Apache** z `mod_rewrite` (+ `mod_ssl`) **lub** **Nginx + PHP-FPM**.
|
|
|
|
### 2.1. Pobranie kodu i zależności
|
|
|
|
```bash
|
|
cd /var/www
|
|
git clone <adres-repo> servicedesk
|
|
cd servicedesk/src
|
|
composer install --no-dev --optimize-autoloader
|
|
```
|
|
|
|
### 2.2. Konfiguracja `.env`
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
Te same zmienne co w sekcji 1.2, z jedną różnicą — `DB_HOST` wskazuje na
|
|
prawdziwy adres serwera bazy, nie na nazwę serwisu Compose:
|
|
|
|
```env
|
|
APP_NAME=Servicedesk
|
|
APP_ENV=production
|
|
APP_DEBUG=false
|
|
APP_URL=https://servicedesk.twoja-domena.pl
|
|
APP_LOCALE=pl
|
|
APP_FALLBACK_LOCALE=pl
|
|
|
|
AUTHOR_CONTACT=helpdesk@twoja-domena.pl
|
|
VERSION=1.1.2
|
|
|
|
DB_CONNECTION=mysql
|
|
DB_HOST=127.0.0.1 # albo adres IP/hostname prawdziwego serwera DB
|
|
DB_PORT=3306
|
|
DB_DATABASE=servicedesk
|
|
DB_USERNAME=servicedesk
|
|
DB_PASSWORD=wygeneruj-silne-haslo
|
|
|
|
SESSION_DRIVER=database
|
|
QUEUE_CONNECTION=database
|
|
```
|
|
|
|
Uzupełnij też `LDAP_*`/`MAIL_*` jak w sekcji 1.2 (to samo ostrzeżenie o
|
|
Admin > Konfiguracja nadpisującym te wartości w locie dotyczy tu identycznie).
|
|
|
|
```bash
|
|
php artisan key:generate
|
|
php artisan migrate --seed
|
|
php artisan storage:link
|
|
```
|
|
|
|
### 2.3. Budowa zasobów
|
|
|
|
```bash
|
|
npm ci
|
|
npm run build
|
|
```
|
|
|
|
(Na maszynie bez Node.js zbuduj `public/build/` gdzie indziej i skopiuj cały
|
|
katalog — to jedyne, co Vite generuje poza źródłem.)
|
|
|
|
### 2.4. Uprawnienia plików
|
|
|
|
```bash
|
|
chown -R www-data:www-data storage bootstrap/cache
|
|
chmod -R 775 storage bootstrap/cache
|
|
```
|
|
|
|
(Zmień `www-data` na użytkownika, pod którym faktycznie działa Apache/PHP-FPM w
|
|
Twojej dystrybucji, np. `apache` na RHEL/CentOS.)
|
|
|
|
### 2.5. Konfiguracja serwera WWW
|
|
|
|
**DocumentRoot musi wskazywać na `public/`**, nigdy na katalog główny aplikacji.
|
|
|
|
**Apache** (`/etc/apache2/sites-available/servicedesk.conf`):
|
|
|
|
```apache
|
|
<VirtualHost *:443>
|
|
ServerName servicedesk.twoja-domena.pl
|
|
DocumentRoot /var/www/servicedesk/src/public
|
|
|
|
<Directory /var/www/servicedesk/src/public>
|
|
AllowOverride All
|
|
Require all granted
|
|
</Directory>
|
|
|
|
SSLEngine on
|
|
SSLCertificateFile /etc/ssl/certs/servicedesk.crt
|
|
SSLCertificateKeyFile /etc/ssl/private/servicedesk.key
|
|
|
|
ErrorLog ${APACHE_LOG_DIR}/servicedesk-error.log
|
|
CustomLog ${APACHE_LOG_DIR}/servicedesk-access.log combined
|
|
</VirtualHost>
|
|
```
|
|
|
|
```bash
|
|
a2enmod rewrite ssl
|
|
a2ensite servicedesk
|
|
systemctl reload apache2
|
|
```
|
|
|
|
> Jeśli kiedykolwiek dodasz własny katalog `public/icons/` — nie rób tego. Stockowy
|
|
> moduł `mod_alias` Apache definiuje `Alias /icons/ "/usr/share/apache2/icons/"`
|
|
> (FancyIndexing), który po cichu przechwytuje `/icons/*` przed dotarciem do
|
|
> Laravela. Ten projekt celowo używa `public/pwa-icons/` z tego właśnie powodu.
|
|
|
|
**Nginx** (+ PHP-FPM):
|
|
|
|
```nginx
|
|
server {
|
|
listen 443 ssl http2;
|
|
server_name servicedesk.twoja-domena.pl;
|
|
root /var/www/servicedesk/src/public;
|
|
|
|
ssl_certificate /etc/ssl/certs/servicedesk.crt;
|
|
ssl_certificate_key /etc/ssl/private/servicedesk.key;
|
|
|
|
index index.php;
|
|
|
|
location / {
|
|
try_files $uri $uri/ /index.php?$query_string;
|
|
}
|
|
|
|
location ~ \.php$ {
|
|
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
|
|
fastcgi_index index.php;
|
|
include fastcgi_params;
|
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
|
}
|
|
|
|
location ~ /\.(?!well-known).* {
|
|
deny all;
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2.6. Zadanie cykliczne (SLA) i kolejka
|
|
|
|
Crontab użytkownika, pod którym stoi aplikacja (np. `www-data`):
|
|
|
|
```cron
|
|
* * * * * cd /var/www/servicedesk/src && php artisan schedule:run >> /dev/null 2>&1
|
|
```
|
|
|
|
Jak w wersji Docker — kolejka (`php artisan queue:work`) nie jest obowiązkowa,
|
|
skoro powiadomienia wysyłają się synchronicznie; zostaw `QUEUE_CONNECTION=database`
|
|
jako bezpieczny domyślny driver na przyszłość.
|
|
|
|
Realtime (patrz 1.3b) potrzebuje tu **długo działającego procesu**
|
|
`php artisan reverb:start` — PHP musi mieć rozszerzenia `pcntl`/`posix`
|
|
(standardowo dostępne, ale sprawdź `php -m`). Najprościej pod systemd:
|
|
|
|
```ini
|
|
# /etc/systemd/system/servicedesk-reverb.service
|
|
[Unit]
|
|
Description=Servicedesk Reverb websocket server
|
|
After=network.target
|
|
|
|
[Service]
|
|
User=www-data
|
|
WorkingDirectory=/var/www/servicedesk/src
|
|
ExecStart=/usr/bin/php artisan reverb:start --host=0.0.0.0 --port=8080
|
|
Restart=always
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
|
|
```bash
|
|
systemctl enable --now servicedesk-reverb
|
|
```
|
|
|
|
Ustaw też te same zmienne `.env` co w 1.3b (`BROADCAST_CONNECTION=reverb`,
|
|
`REVERB_*`, `VITE_REVERB_*` — tu `REVERB_HOST` to po prostu `127.0.0.1`, nie
|
|
nazwa usługi compose) i skieruj serwer WWW tak, by ścieżka `/app*` trafiała do
|
|
portu 8080 zamiast do PHP-FPM/Apache (osobny `location`/`VirtualHost` dla tej
|
|
jednej ścieżki, analogicznie do reguły Traefika w 1.3b).
|
|
|
|
### 2.7. Pierwsze logowanie i dalsza konfiguracja
|
|
|
|
Identycznie jak w kroku 1.6 — zaloguj się `admin@example.com` / `admin`, zmień
|
|
hasło, uzupełnij prawdziwe LDAP/SMTP w Admin > Konfiguracja (placeholdery z seeda
|
|
inaczej realnie próbują łączyć się z fałszywymi adresami), przetestuj oba
|
|
połączenia przyciskiem „Testuj połączenie”.
|
|
|
|
### 2.8. Aktualizacje (bez przestoju)
|
|
|
|
```bash
|
|
cd /var/www/servicedesk/src
|
|
git pull
|
|
composer install --no-dev --optimize-autoloader
|
|
php artisan migrate --force
|
|
npm ci && npm run build
|
|
php artisan config:clear # tylko jeśli wcześniej użyto config:cache
|
|
```
|
|
|
|
Nie ma potrzeby restartu Apache/PHP-FPM dla samych zmian w PHP/Blade — restart
|
|
przyda się tylko po zmianie w `.env` lub konfiguracji samego serwera WWW.
|