v1.0.1
Some checks failed
Build and push image / build (push) Failing after 3m17s

Documentation overhaul (TESTING/CONTRIBUTING/ARCHITECTURE/SECURITY/CLAUDE.md,
CHANGELOG.md, drop unmaintained src/README.md) plus CI-built Docker images:
Gitea Actions now builds and pushes the servicedesk image to the Gitea
container registry on Dockerfile changes, and compose.yaml pulls that image
instead of building locally. No application behavior changes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-22 01:29:43 +02:00
parent b33b217bdb
commit 13a758779d
13 changed files with 576 additions and 71 deletions

16
.env.example Normal file
View File

@@ -0,0 +1,16 @@
# Copy to .env (gitignored) — this is the Docker Composelevel env file, read by
# compose.yaml only. It is separate from src/.env, which configures the Laravel
# app itself (see src/.env.example and install.md).
HOSTNAME=servicedesk.twoja-domena.pl
# Database
MYSQL_ROOT_PASSWORD=wygeneruj-silne-haslo
MYSQL_DATABASE=servicedesk
MYSQL_USER=servicedesk
MYSQL_PASSWORD=wygeneruj-inne-silne-haslo
# Which image tag to deploy (built by CI, see .gitea/workflows/build.yml).
# Defaults to "latest" if unset — pin to a specific commit SHA tag to control
# exactly when this host picks up a new image.
# IMAGE_TAG=latest

View File

@@ -0,0 +1,42 @@
name: Build and push image
# The app image only provides PHP/Apache/extensions — application code is bind-
# mounted from ./src at deploy time (see compose.yaml), so this only needs to
# run when the image definition itself changes, not on every app code change.
on:
push:
branches: [main]
paths:
- Dockerfile
- .gitea/workflows/build.yml
permissions:
contents: read
packages: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Gitea container registry
uses: docker/login-action@v3
with:
registry: gitea.kzbikowski.pl
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: |
gitea.kzbikowski.pl/kzbkowski/servicedesk:latest
gitea.kzbikowski.pl/kzbkowski/servicedesk:${{ github.sha }}

112
ARCHITECTURE.md Normal file
View File

@@ -0,0 +1,112 @@
# Architecture
Server-rendered Laravel + Livewire app (no SPA/API-driven frontend for the app
itself — the REST API in `routes/api.php` exists purely for external
integrations). See [README.md](README.md) for the feature list and tech stack;
this doc covers how the pieces fit together.
## Request flow
1. `routes/web.php` gates every area behind `auth` + a role middleware
(`role:client`, `role:operator`, `role:admin``App\Http\Middleware\EnsureRole`),
which checks the role against `$user->roles`. A user can hold multiple roles at
once; the router just requires *one* of the listed roles per route group.
2. Each route resolves to a full-page Livewire component under
`app/Livewire/{Client,Operator,Admin,Auth}/` — there are no traditional
controllers rendering Blade views for these areas (the REST API in
`routes/api.php` is the exception, backed by `app/Http/Controllers/Api/`).
3. Livewire components call into `app/Services/TicketService.php` for anything
that mutates ticket state (create/transition/reply/notify) rather than
mutating models directly — keep that convention when adding new mutations so
notification/history/SLA side effects stay in one place.
4. `App\Providers\AppServiceProvider::boot()` runs a settings override pass on
every request (`applyLdapSettingsOverride`, `applyMailSettingsOverride`,
`applySessionSettingsOverride`, `applyTimezoneSettingsOverride`) — see
"Settings override" below.
## Data model
Core tables/models (`app/Models/`):
```
Category ─< Subcategory ─< CustomField (per-subcategory custom fields)
└──< Ticket >── Team (subcategory routes to a team)
├──< TicketMessage (public replies + internal notes)
├──< TicketAttachment
├──< TicketHistory
├── customer/assignee → User
├── status → Status (fixed stages: new/open/closed)
└── priority → Priority → SlaRule (response/resolution minutes)
User ─< UserFieldValue >─ UserField
ApiClient (Sanctum token owner, ability-scoped)
Setting (single-row-per-key config store, see below)
ReplyQuickAction, ResponseTemplate, EmailTemplate, NotificationSetting
```
`Ticket` (`app/Models/Ticket.php`) is the largest model — it owns SLA math
(`slaInfo()`, `isOverdue()`, `resolutionDeadline()`), status/priority display
helpers (`statusLabel()`, `tagStyleFromColor()`), operator-visibility scoping
(`scopeVisibleToOperator`, `isVisibleToOperator` — a team member sees their team's
queue + unassigned + anything assigned to them, an admin sees everything), and
work-timer tracking (`timerElapsedSeconds()`). Keep ticket-shaped logic here
rather than spreading it across Livewire components.
## Roles & permissions
Roles are a plain array on the user (`$user->roles`), not a separate pivot-backed
package — checked via `EnsureRole` at the route level. Every account gets
`client` by default (`App\Ldap\Handlers\AssignDefaultRole` for LDAP-provisioned
accounts); staff switch areas via the header role switcher, but always land on
`/client` first after login.
## Authentication
`config/auth.php` defines the default `web` guard against an LDAP-backed user
provider (LdapRecord); a plain Eloquent provider is kept alongside it only for
local tooling/tests that don't hit a directory. In production, LDAP bind is the
primary path; the local fallback account (`admin@example.com` from the seeder)
authenticates against a local password when the LDAP bind doesn't match — this is
the account used for first login after a fresh install (see
[install.md](install.md)).
`app/Ldap/Handlers/` hooks into LdapRecord's import/sync events:
`AssignDefaultRole` grants the `client` role to new LDAP-provisioned accounts,
`SyncUserFieldsFromLdap` keeps `UserFieldValue` rows in sync with directory
attributes.
## Settings override ("live config")
`App\Support\Settings` (`app/Support/Settings.php`) is a cached key/value reader
over the `settings` table, with hardcoded defaults for every key (company name,
LDAP/SMTP connection details, attachment limits, session lifetime, timezone,
branding/email HTML, etc.). Admin > Konfiguracja writes to this table, and
`AppServiceProvider::boot()` re-applies the relevant subset of it over
`config()` on every request — meaning **`Setting` rows win over `.env`** for
LDAP, mail, session lifetime and timezone once they're non-empty. This is by
design (lets an admin reconfigure LDAP/SMTP without a redeploy) but is also the
source of the "seeded placeholder overrides real `.env` values" gotcha
documented in [install.md](install.md) — anything touching LDAP/mail/session/
timezone config should go through `Settings`, not raw `config()`/`.env` reads.
## SLA
`SlaRule` holds per-priority response/resolution targets in minutes. The
scheduled command `tickets:check-sla-breaches` (registered in
`routes/console.php`, run every 15 minutes via `schedule:run`) flags overdue
tickets and can notify the assigned operator — see [install.md](install.md) for
why this requires an external cron entry (the Docker image ships no
cron/supervisor of its own).
## API
`routes/api.php` + `app/Http/Controllers/Api/` expose a small ability-scoped REST
surface over Sanctum tokens (`tickets:read`, `tickets:write`,
`dictionaries:read`, `users:read`), issued via admin-managed `ApiClient` records.
Rate limiting is configured per-client (120 req/min keyed by client ID) vs. a
tighter per-IP limit for unauthenticated requests
(`AppServiceProvider::configureApiRateLimiting()`). Interactive docs are
generated by L5-Swagger at `/admin/api-docs`; there is no static Markdown API
reference in-repo.

43
CHANGELOG.md Normal file
View File

@@ -0,0 +1,43 @@
# Changelog
All notable changes to this project are documented in this file. Format loosely
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## [1.0.1] - 2026-07-22
Documentation and deployment/CI overhaul — no application behavior changes.
- Added project docs: `TESTING.md`, `CONTRIBUTING.md`, `ARCHITECTURE.md`,
`SECURITY.md`, `CLAUDE.md`; removed the unmaintained stock Laravel
`src/README.md`.
- Added `.gitea/workflows/build.yml`: Gitea Actions now builds and pushes the
`servicedesk` image to the Gitea container registry whenever `Dockerfile`
changes on `main`.
- `compose.yaml` now pulls `image: gitea.kzbikowski.pl/kzbkowski/servicedesk:${IMAGE_TAG:-latest}`
instead of building locally; `mariadb` pinned to `mariadb:12.3`; added a
`mariadb` healthcheck and `depends_on: condition: service_healthy` for
`servicedesk`.
- Added tracked templates `compose.yaml.example` and `.env.example` (root) for
the previously-untracked `compose.yaml`/`.env`.
- Documented the new pull-based deploy flow and one-time registry login in
`install.md`.
## [1.0.0] - 2026-07-21
Initial release.
- Ticketing core: categories/subcategories with per-subcategory custom fields,
statuses, priorities, teams, attachments, message threads (public replies +
internal notes), history log, merge/delete.
- SLA rules per priority with a scheduled breach check (`tickets:check-sla-breaches`,
every 15 minutes).
- Response templates, quick actions, and per-event HTML email templates/
notification toggles.
- Operator statistics dashboard (`/operator/stats`) with KPI tiles and breakdowns.
- Branding/config panel: company identity, LDAP connection + user sync, SMTP,
attachment limits, session lifetime, timezone.
- LDAP authentication (LdapRecord) with local-account fallback.
- REST API (`/api/v1/...`) via Sanctum, ability-scoped (`tickets:read`,
`tickets:write`, `dictionaries:read`, `users:read`), with Swagger docs at
`/admin/api-docs`.
- Installable PWA manifest/icons for the client-facing area.

78
CLAUDE.md Normal file
View File

@@ -0,0 +1,78 @@
# CLAUDE.md
Guidance for AI coding agents working in this repo. See [README.md](README.md)
for the feature/tech overview, [ARCHITECTURE.md](ARCHITECTURE.md) for how the app
is put together, and [install.md](install.md) for full deployment instructions.
## This is a live production system
The only real user today is the owner's own account (client+operator+admin
roles). Treat the running database as production, not a sandbox:
- Never create/modify/delete real DB records (users, tickets, settings, etc.)
without the user explicitly asking. Don't spin up throwaway test users via
`php artisan tinker` against this DB.
- For UI/CSS verification, prefer an offline static-HTML harness reproducing the
real markup+CSS, or ask for test credentials, rather than poking at prod data.
- Production is fronted by Traefik with a **private-CA TLS cert** (not publicly
trusted) — tools like `curl`/Playwright need `-k` / `ignore_https_errors` to
hit it directly.
## Container operations: use `sudo`, never build the image locally
All Docker commands against this stack need `sudo` (e.g.
`sudo docker compose exec servicedesk ...`, `sudo docker exec servicedesk-servicedesk-1 ...`).
**Never run `docker build`, `docker compose build`, or `--build`.** The
`servicedesk` image is built by CI (`.gitea/workflows/build.yml`, triggered on
`Dockerfile` changes on `main`) and pushed to the Gitea container registry;
`compose.yaml` only ever `pull`s a tag (`sudo docker compose pull && sudo docker
compose up -d`, see [install.md](install.md) 1.3/1.3a) — building locally would
just diverge from what CI produces. The app container
(`servicedesk-servicedesk-1`) mounts `./src` from the host over NFS
(`/mnt/rabbit-containers` → NFS export), so plain file edits already take effect
with no rebuild or restart:
- Blade/PHP/route edits: just edit the files — live instantly, no restart needed.
- `resources/css/app.css` / `resources/js/*` (Vite/Tailwind entrypoints) **do**
need a rebuild — `public/build/assets/` is static compiled output. Neither the
host nor the app container has Node installed; rebuild with a throwaway
container instead of touching the app image:
```bash
sudo docker run --rm -v "$(pwd)/src":/app -w /app node:22 npm run build
```
(run from the repo root; `node_modules` already exists, no install needed).
Verify via `public/build/manifest.json` picking up a new hash.
- After running artisan cache commands for diagnostics (`config:cache`,
`view:cache`), clear them again afterward (`config:clear`/`view:clear`) — this
app normally runs uncached so edits apply live; leaving a cache on silently
breaks that workflow.
## Apache `/icons/` alias trap
The stock `php:apache` image enables `mods-enabled/alias.conf`, which defines
`Alias /icons/ "/usr/share/apache2/icons/"`. Any app-level static directory at
`public/icons/` is silently shadowed by Apache's own stock icon set — requests
404 before ever reaching Laravel, with no useful log line. This project
deliberately uses `public/pwa-icons/` for PWA manifest icons for exactly this
reason — never add a `public/icons/` directory.
## Established UI conventions
- **Post-login redirect** always lands on `/client` (`User::defaultArea()` in
`app/Models/User.php`), even for accounts holding operator/admin roles too —
staff switch areas via the role switcher in the header
(`resources/views/components/profile-menu.blade.php`). Keep `/client`
first-priority in `defaultArea()` if you add new roles/areas.
- **Mobile tables**: don't rely on horizontal scroll alone for wide data tables.
The established pattern (`.table-cards-mobile` in `resources/css/app.css`,
`@media (max-width:640px)`) turns each `<tr>` into a card with `data-label`
attributes on `<td>`s. Currently applied to the operator ticket queue; apply
the same treatment to any other wide table you add or make mobile-relevant
(admin panel tables don't have it yet).
## Testing & code style
See [TESTING.md](TESTING.md) and [CONTRIBUTING.md](CONTRIBUTING.md) — run
`php artisan test` and `./vendor/bin/pint` before considering a change done.
There is no CI; local test runs are the only gate.

55
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,55 @@
# Contributing
Internal helpdesk project for a single production deployment — this guide covers
the practical local workflow, not an open-source contribution process.
## Local setup
See [install.md](install.md) for full environment setup (Docker Compose or
bare-metal). For day-to-day development the app container mounts `./src`
directly, so PHP/Blade/route changes apply immediately — no rebuild or restart
needed. CSS/JS changes need a Vite build (see the "Local/dev notes" section of
[README.md](README.md)); Node isn't installed on the host or in the app image, so
build through a throwaway `node:22` container as documented there.
## Before opening a PR / merging
1. **Run the test suite** — see [TESTING.md](TESTING.md) for details:
```bash
docker compose exec servicedesk php artisan test
```
2. **Run Pint** (Laravel's code-style fixer, default preset, no project overrides):
```bash
docker compose exec servicedesk ./vendor/bin/pint
```
3. If you changed anything under `resources/`, rebuild the frontend bundle and
commit the result if `public/build/` is tracked, or confirm the deploy step
will rebuild it (see [install.md](install.md)).
4. If you touched the data model, add/update a migration rather than editing an
existing one that has already shipped, and update
[ARCHITECTURE.md](ARCHITECTURE.md) if the change affects the ticket lifecycle
or role/permission model.
## Commit messages
Short, imperative summary line (e.g. `Add SLA breach email toggle`); add a body
only when the *why* isn't obvious from the diff.
## Code organization
Follow the existing structure rather than introducing new patterns:
- `app/Livewire/{Client,Operator,Admin,Auth}/` — one component per screen/area,
gated by the matching route middleware (`role:client`, `role:operator`,
`role:admin`).
- `app/Services/TicketService.php` — ticket lifecycle logic (create/transition/
notify) lives here, not in Livewire components.
- `app/Models/` — one Eloquent model per table; keep query scopes and display/
formatting helpers (labels, style/color helpers) on the model as done for
`Ticket` (`statusLabel()`, `slaInfo()`, etc.) rather than duplicating them in views.
- `database/migrations/` — one migration per table group, representing final
shape (not an incremental history to replay for intuition).
- `routes/web.php` / `routes/api.php` — keep role/ability gating at the route
group level, matching the existing pattern.
See [ARCHITECTURE.md](ARCHITECTURE.md) for how these pieces fit together.

View File

@@ -66,9 +66,12 @@ and **[wiki/admin](wiki/admin/README.md)** for role-specific how-to guides.
dashboard is hand-rolled inline-styled bar/column charts, so it needs no client
build step beyond the CSS bundle.
- **Database**: MariaDB.
- **Deployment**: `compose.yaml``servicedesk` (php:apache, source bind-mounted
from `./src`, no image rebuild needed for PHP/Blade/route changes) + `mariadb`,
fronted by Traefik with a private-CA TLS cert.
- **Deployment**: `compose.yaml``servicedesk` (source bind-mounted from `./src`,
no image rebuild needed for PHP/Blade/route changes) + `mariadb`, fronted by
Traefik with a private-CA TLS cert. The `servicedesk` image itself is built and
pushed by Gitea Actions (`.gitea/workflows/build.yml`) to the Gitea container
registry whenever `Dockerfile` changes — `compose.yaml` just pulls a tag, it
never builds locally.
See **[install.md](install.md)** for full step-by-step deployment instructions —
both via Docker Compose (this stack) and directly on a server with Apache/Nginx,

54
SECURITY.md Normal file
View File

@@ -0,0 +1,54 @@
# Security Policy
This is an internally-run production helpdesk (not an open-source project with a
public disclosure program). If you find a vulnerability affecting this
deployment, report it directly rather than opening a public GitHub issue:
- **Contact**: the address configured as `AUTHOR_CONTACT` in `src/.env`
(surfaced in the app under Admin > O aplikacji).
- Please include steps to reproduce and, if applicable, which role/area
(Client/Operator/Admin/API) is affected.
Do not test against the production instance beyond what's needed to demonstrate
the issue — no automated scanning, load testing, or bulk data extraction.
## Scope & sensitive data
This system holds real ticket content, user PII (names/emails, and anything
submitted in ticket bodies/custom fields), and LDAP/SMTP connection credentials.
Treat access to the `admin` area, the `settings` table, and any `.env` file as
credential-equivalent.
## Notable design points relevant to security review
- **Auth**: LDAP bind is the primary login path (`config/auth.php`,
`directorytree/ldaprecord-laravel`); a local fallback account
(`admin@example.com`, seeded — **must** have its password changed after
install, see [install.md](install.md)) exists for when LDAP is unavailable or
misconfigured.
- **Settings override**: Admin > Konfiguracja values in the `settings` table
override `.env` for LDAP/SMTP/session/timezone config at runtime (see
[ARCHITECTURE.md](ARCHITECTURE.md) — "Settings override"). This means a
compromised admin account can redirect LDAP/SMTP traffic without touching the
filesystem — restrict Admin-role accounts accordingly.
- **API**: Sanctum tokens are ability-scoped (`tickets:read`, `tickets:write`,
`dictionaries:read`, `users:read`) and issued per `ApiClient` via the admin
panel; rate-limited per-client (authenticated) or per-IP (unauthenticated) —
see `AppServiceProvider::configureApiRateLimiting()`.
- **Role model**: roles are checked via `EnsureRole` middleware against
`$user->roles`; there's no per-object ACL beyond team-based ticket visibility
(`Ticket::scopeVisibleToOperator`) — any change to that scope directly changes
what an operator can see across teams.
- **Attachments**: size/count/type limits are admin-configurable
(`attachment_max_size_kb`, `attachment_allowed_types`, etc. in `Settings`) —
don't bypass them when adding new upload paths.
- **TLS**: production traffic terminates at Traefik with a private CA
certificate (not publicly trusted) — this is expected for this deployment, not
a misconfiguration.
## Dependencies
No automated dependency-vulnerability scanning (e.g. Dependabot, `composer
audit` in CI) is currently configured — there is no CI pipeline for this repo at
all (see [TESTING.md](TESTING.md)). Run `composer audit` / `npm audit` manually
before major dependency bumps.

64
TESTING.md Normal file
View File

@@ -0,0 +1,64 @@
# Testing
Tests live in `src/tests/` and run on [Pest 4](https://pestphp.com) (with the Laravel
plugin), backed by PHPUnit's runner. `src/phpunit.xml` configures two suites,
`Unit` and `Feature` (almost everything lives in `Feature/` — end-to-end Livewire
component and API tests), running against an in-memory SQLite database
(`DB_CONNECTION=sqlite`, `DB_DATABASE=:memory:`) so tests never touch the real
MariaDB instance. Mail, queue, cache, session and broadcasting are all swapped for
fast in-process fakes (`array`/`sync`) for the same reason.
## Running the suite
From inside the app container (or on a bare-metal install, from `src/`):
```bash
docker compose exec servicedesk php artisan test
```
or directly with Pest:
```bash
docker compose exec servicedesk ./vendor/bin/pest
```
Run a single file or filter by name:
```bash
docker compose exec servicedesk php artisan test --filter=SlaBreachNotificationTest
docker compose exec servicedesk ./vendor/bin/pest tests/Feature/TicketApiTest.php
```
There is no CI pipeline configured for this repository — running the suite
locally/in-container before merging or deploying is the only gate today.
## What's covered
The `Feature/` suite is organized by area and is the main source of truth for
expected behavior — read the relevant test before changing logic in that area:
- **Admin**: category/subcategory + custom fields, teams, users, branding, status/
priority reordering, response templates, email templates & notification toggles,
SMTP/timezone/session-lifetime config.
- **Operator**: ticket queue (search/sort/columns, bulk actions, closed tab, team
scoping), ticket detail editing, quick actions, time tracking.
- **Client**: new ticket submission.
- **Auth/LDAP**: LDAP login, LDAP-restricted guest ticket creation + local-account
fallback, account-creation toggles.
- **API**: ability-scoped Sanctum enforcement (`ApiAbilityEnforcementTest`), API key
management, tickets/messages/users/dictionaries endpoints.
- **Cross-cutting**: role middleware, SLA breach notifications, attachment limits,
ticket business rules (status/priority transitions, merging, history log).
`tests/Pest.php` wires up `Tests\TestCase` (Laravel's `RefreshDatabase`-style base)
for the whole suite — new test files under `tests/Feature/` pick this up
automatically without extra boilerplate.
## Code style
`laravel/pint` is installed as a dev dependency (no custom `pint.json`, so it runs
on Laravel's default preset). Run it before committing:
```bash
docker compose exec servicedesk ./vendor/bin/pint
```

50
compose.yaml.example Normal file
View File

@@ -0,0 +1,50 @@
# Copy to compose.yaml (gitignored — the real file stays untracked, same as .env)
# and adjust HOSTNAME/image/registry as needed for your deployment.
services:
servicedesk:
image: gitea.kzbikowski.pl/kzbkowski/servicedesk:${IMAGE_TAG:-latest}
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.servicedesk.rule=Host(`${HOSTNAME}`)
- traefik.http.routers.servicedesk.entrypoints=websecure
# - traefik.http.routers.servicedesk.tls.certresolver=tls-resolver
- traefik.http.routers.servicedesk.tls=true
mariadb:
image: mariadb:12.3
restart: unless-stopped
networks:
- internal
command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
volumes:
- ./mysql:/var/lib/mysql
ports:
- "3605:3306"
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
labels:
- com.centurylinklabs.watchtower.enable=true
networks:
internal:
traefik_public:
external: true

View File

@@ -28,9 +28,17 @@ osobne pliki, w dwóch różnych miejscach.
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. Plik `.env` w katalogu głównym (Docker Compose)
### 1.1. Pliki `compose.yaml` i `.env` w katalogu głównym
Skopiuj/utwórz `.env` obok `compose.yaml`:
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
@@ -38,6 +46,7 @@ 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
@@ -45,6 +54,8 @@ MYSQL_PASSWORD=wygeneruj-inne-silne-haslo
- `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)
@@ -100,17 +111,52 @@ MAIL_FROM_ADDRESS=noreply@twoja-domena.pl
MAIL_FROM_NAME="${APP_NAME}"
```
### 1.3. Budowa i start kontenerów
### 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 up -d --build
docker compose pull
docker compose up -d
```
`--build` jest potrzebny **tylko przy pierwszym uruchomieniu** (budowa obrazu z
`Dockerfile`). Później, przy zwykłych zmianach w kodzie PHP/Blade — źródło jest
zamontowane z `./src`, więc `docker compose restart` (albo nic — Laravel odświeża
się natychmiast) wystarczy; `--build`/`docker compose build` uruchamiaj tylko gdy
zmienia się sam `Dockerfile`.
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>`.
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.4. Instalacja aplikacji wewnątrz kontenera

View File

@@ -5,7 +5,7 @@ APP_DEBUG=true
APP_URL=http://localhost
AUTHOR_CONTACT=helpdesk@kzbikowski.pl
VERSION=1.0.0
VERSION=1.0.1
APP_LOCALE=en
APP_FALLBACK_LOCALE=en

View File

@@ -1,58 +0,0 @@
<p align="center"><a href="https://laravel.com" target="_blank"><img src="https://raw.githubusercontent.com/laravel/art/master/logo-lockup/5%20SVG/2%20CMYK/1%20Full%20Color/laravel-logolockup-cmyk-red.svg" width="400" alt="Laravel Logo"></a></p>
<p align="center">
<a href="https://github.com/laravel/framework/actions"><img src="https://github.com/laravel/framework/workflows/tests/badge.svg" alt="Build Status"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/dt/laravel/framework" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/v/laravel/framework" alt="Latest Stable Version"></a>
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/l/laravel/framework" alt="License"></a>
</p>
## About Laravel
Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as:
- [Simple, fast routing engine](https://laravel.com/docs/routing).
- [Powerful dependency injection container](https://laravel.com/docs/container).
- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage.
- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent).
- Database agnostic [schema migrations](https://laravel.com/docs/migrations).
- [Robust background job processing](https://laravel.com/docs/queues).
- [Real-time event broadcasting](https://laravel.com/docs/broadcasting).
Laravel is accessible, powerful, and provides tools required for large, robust applications.
## Learning Laravel
Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework.
In addition, [Laracasts](https://laracasts.com) contains thousands of video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library.
You can also watch bite-sized lessons with real-world projects on [Laravel Learn](https://laravel.com/learn), where you will be guided through building a Laravel application from scratch while learning PHP fundamentals.
## Agentic Development
Laravel's predictable structure and conventions make it ideal for AI coding agents like Claude Code, Cursor, and GitHub Copilot. Install [Laravel Boost](https://laravel.com/docs/ai) to supercharge your AI workflow:
```bash
composer require laravel/boost --dev
php artisan boost:install
```
Boost provides your agent 15+ tools and skills that help agents build Laravel applications while following best practices.
## Contributing
Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions).
## Code of Conduct
In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct).
## Security Vulnerabilities
If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed.
## License
The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).