feat: Initial commit.

This commit is contained in:
2026-04-16 12:58:54 +02:00
commit 6caad6ee97
29 changed files with 518 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
.git
php/_logs/*.log
php/Dockerfile
+43
View File
@@ -0,0 +1,43 @@
name: Build and Push Docker Image
on:
push:
brancher:
- main
jobs:
changes:
runs-on: ubuntu-latest
outputs:
apache: ${{ steps.filter.outputs.apache }}
php: ${{ steps.filter.outputs.php }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Detect changed folders
id: filter
run: |
echo "apache=$(git diff --name-only HEAD~1 HEAD | grep '^apache/' | wc -l | grep -q '^0$' && echo false || echo true)" >> $GITHUB_OUTPUT
echo "php=$(git diff --name-only HEAD~1 HEAD | grep '^php/' | wc -l | grep -q '^0$' && echo false || echo true)" >> $GITHUB_OUTPUT
build-apache:
needs: changes
if: ${{ needs.changes.outputs.apache == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login ${{ secrets.REGISTRY_URL }} -u ${{ secrets.REGISTRY_USER }} --password-stdin
- run: docker build -t ${{ secrets.REGISTRY_URL }}/${{ gitea.repository }}/apache:latest ./apache
- run: docker push ${{ secrets.REGISTRY_URL }}/${{ gitea.repository }}/apache:latest
build-php:
needs: changes
if: ${{ needs.changes.outputs.php == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- run: echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login ${{ secrets.REGISTRY_URL }} -u ${{ secrets.REGISTRY_USER }} --password-stdin
- run: docker build -t ${{ secrets.REGISTRY_URL }}/${{ gitea.repository }}/php:latest ./php
- run: docker push ${{ secrets.REGISTRY_URL }}/${{ gitea.repository }}/php:latest
+1
View File
@@ -0,0 +1 @@
app/_logs/*.log
+18
View File
@@ -0,0 +1,18 @@
FROM httpd:2.4
RUN apt update && \
apt install -y curl
COPY apache/apache_vhost.conf /usr/local/apache2/conf/sites-enabled/sslguard.skyger.cz.conf
COPY apache/my-modules.conf /usr/local/apache2/conf/extra/my-modules.conf
RUN echo "Include conf/extra/my-modules.conf" \
>> /usr/local/apache2/conf/httpd.conf
RUN echo "Include conf/sites-enabled/sslguard.skyger.cz.conf" \
>> /usr/local/apache2/conf/httpd.conf
RUN echo "RemoteIPHeader X-Forwarded-For" \
>> /usr/local/apache2/conf/httpd.conf
RUN echo "RemoteIPTrustedProxy 172.16.0.0/12" \
>> /usr/local/apache2/conf/httpd.conf
#RUN apachectl configtest && apachectl graceful
+34
View File
@@ -0,0 +1,34 @@
<VirtualHost *:80>
ServerName sslguard.skyger.cz
ServerAlias www.sslguard.skyger.cz
ServerAdmin admin@sslguard.skyger.cz
DocumentRoot /domains/sslguard.skyger.cz/www/
ErrorLog /domains/sslguard.skyger.cz/_logs/www/http-error.log
CustomLog /domains/sslguard.skyger.cz/_logs/www/http-access.log combined
<Directory /domains/sslguard.skyger.cz/>
Options -Indexes
AllowOverride All
Require all granted
</Directory>
ProxyPassMatch "^/(.*\.php(/.*)?)$" "fcgi://php-fpm:9000/domains/sslguard.skyger.cz/www/$1"
</VirtualHost>
<VirtualHost *:80>
ServerName api.sslguard.skyger.cz
ServerAdmin admin@sslguard.skyger.cz
DocumentRoot /domains/sslguard.skyger.cz/api/
ErrorLog /domains/sslguard.skyger.cz/_logs/api/http-error.log
CustomLog /domains/sslguard.skyger.cz/_logs/api/http-access.log combined
<Directory /domains/sslguard.skyger.cz/>
Options -Indexes
AllowOverride All
Require all granted
</Directory>
ProxyPassMatch "^/(.*\.php(/.*)?)$" "fcgi://php-fpm:9000/domains/sslguard.skyger.cz/api/$1"
</VirtualHost>
+4
View File
@@ -0,0 +1,4 @@
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule remoteip_module modules/mod_remoteip.so
View File
View File
View File
View File
+38
View File
@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace App;
use Nette\Bootstrap\Configurator;
class Bootstrap
{
public static function boot(): Configurator
{
$configurator = new Configurator;
$appDir = dirname(__DIR__);
$configurator->setDebugMode(true);
$configurator->enableTracy($appDir . '/_logs');
$configurator->setTimeZone('Europe/Prague');
$configurator->setTempDirectory($appDir . '/tmp');
$configurator->createRobotLoader()
->addDirectory(__DIR__)
->register();
$configurator->addConfig($appDir . '/app/config/common.neon');
$configurator->addConfig($appDir . '/app/config/services.neon');
$configurator->addConfig($appDir . '/app/config/local.neon');
// use ENV variables from PHP
/*$configurator->addDynamicParameters([
'env' => getenv(),
]);*/
return $configurator;
}
}
+34
View File
@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace App\Presenters;
use Nette\Application\UI\Presenter;
use Predis\Client as PredisClient;
use Kdyby\Redis\RedisStorage;
use Kdyby\Redis\RedisClient;
use Nette\Caching\Cache;
class BasePresenter extends Presenter
{
// load shared functions
use SharedTrait;
// define properties
protected array $constants;
protected Cache $cache;
// DI constants from local.neon
public function __construct(array $constants, RedisStorage $cacheStorage) {
parent::__construct();
$this->constants = $constants;
$this->cache = new Cache($cacheStorage);
}
protected function getConstant(string $name) {
return $this->constants[$name] ?? null;
}
}
+13
View File
@@ -0,0 +1,13 @@
<?php
namespace App\Presenters;
use Nette\Application\UI\Presenter;
final class ErrorPresenter extends Presenter
{
public function renderDefault(): void
{
$this->template->message = "An error occurred.";
}
}
+24
View File
@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace App\Presenters;
use Nette\Application\UI\Presenter;
final class HomepagePresenter extends BasePresenter
{
protected array $constants;
// load params from templates
/*public function __construct(array $constants, RedisStorage $cacheStorage)
{
parent::__construct($constants, $cacheStorage);
$this->constants = $constants;
}*/
// default content
public function actionDefault(): void
{
}
}
+46
View File
@@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
namespace App\Presenters;
use Nette\Application\UI\Form;
trait SharedTrait {
// important for Bootstrap Forms visualisation
function makeBootstrap4(Form $form): void
{
$renderer = $form->getRenderer();
$renderer->wrappers['controls']['container'] = null;
$renderer->wrappers['pair']['container'] = 'div class="row form-group align-items-center justify-content-center py-2 login"';
$renderer->wrappers['pair']['.error'] = 'has-danger';
$renderer->wrappers['control']['container'] = 'div class=col-sm-9';
$renderer->wrappers['label']['container'] = 'div class="col-sm-3 col-form-label"';
$renderer->wrappers['control']['description'] = 'span class=form-text';
$renderer->wrappers['control']['errorcontainer'] = 'span class=form-control-feedback';
$renderer->wrappers['control']['.error'] = 'is-invalid';
foreach ($form->getControls() as $control) {
$type = $control->getOption('type');
if ($type === 'button') {
$control->getControlPrototype()->addClass(empty($usedPrimary) ? 'btn btn-primary' : 'btn btn-secondary');
$usedPrimary = true;
} elseif (in_array($type, ['text', 'textarea', 'select'], true)) {
$control->getControlPrototype()->addClass('form-control');
} elseif ($type === 'file') {
$control->getControlPrototype()->addClass('form-control-file');
} elseif (in_array($type, ['checkbox', 'radio'], true)) {
if ($control instanceof Nette\Forms\Controls\Checkbox) {
$control->getLabelPrototype()->addClass('form-check-label');
} else {
$control->getItemLabelPrototype()->addClass('form-check-label');
}
$control->getControlPrototype()->addClass('form-check-input');
$control->getSeparatorPrototype()->setName('div')->addClass('form-check');
}
}
}
}
@@ -0,0 +1 @@
HELLO
+21
View File
@@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace App\Router;
use Nette;
use Nette\Application\Routers\RouteList;
final class RouterFactory
{
use Nette\StaticClass;
public static function createRouter(): RouteList
{
$router = new RouteList;
$router->addRoute('<presenter>/<action>[/<id>]', 'Homepage:default');
return $router;
}
}
+13
View File
@@ -0,0 +1,13 @@
parameters:
application:
errorPresenter: Error
mapping:
*: App\*Module\Presenters\*Presenter
session:
expiration: 60 minutes
debugger: true
di:
export:
parameters: no
tags: no
+11
View File
@@ -0,0 +1,11 @@
parameters:
constants:
DEBUG_MODE: true
DEBUG_FILE: 'debug.log'
ERROR_FILE: 'error.log'
LOGS_DIR: %appDir%/../_logs/
database:
dsn: 'mysql:host=db;dbname=${DB_DB};port=3306'
user: 'sslguard-skyger-cz'
password: 'gsjlqfdaldw08qpihrsax'
+20
View File
@@ -0,0 +1,20 @@
services:
redis.client:
factory: Kdyby\Redis\RedisClient('keydb', 6379)
cache.storage:
factory: Kdyby\Redis\RedisStorage(@redis.client)
basePresenter:
class: App\Presenters\BasePresenter
arguments:
- %constants%
- @cache.storage
homepagePresenter:
class: App\Presenters\HomepagePresenter
arguments:
- %constants%
- @cache.storage
- App\Router\RouterFactory::createRouter
View File
+37
View File
@@ -0,0 +1,37 @@
# Apache configuration file (see https://httpd.apache.org/docs/current/mod/quickreference.html)
Require all granted
# disable directory listing
<IfModule mod_autoindex.c>
Options -Indexes
</IfModule>
# enable cool URL
<IfModule mod_rewrite.c>
RewriteEngine On
#RewriteCond %{HTTPS} off
#RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# RewriteBase /
# prevents files starting with dot to be viewed by browser
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule /\.|^\.(?!well-known/) - [F]
# front controller
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !\.(pdf|js|mjs|ico|gif|jpg|jpeg|png|webp|svg|css|rar|zip|7z|tar\.gz|map|eot|ttf|otf|woff|woff2)$ index.php [L]
</IfModule>
# enable gzip compression
<IfModule mod_deflate.c>
<IfModule mod_filter.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/javascript application/json application/xml image/svg+xml
</IfModule>
</IfModule>
# enable index files
<IfModule dir_module>
DirectoryIndex index.php index.html
</ifModule>
+10
View File
@@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
require __DIR__ . '/../vendor/autoload.php';
$configurator = App\Bootstrap::boot();
$container = $configurator->createContainer();
$application = $container->getByType(Nette\Application\Application::class);
$application->run();
+2
View File
@@ -0,0 +1,2 @@
User-agent: *
Disallow: /
+90
View File
@@ -0,0 +1,90 @@
version: '3'
services:
# certbot:
# image: certbot/certbot:latest
# container_name: certbot
# volumes:
# - ./certbot/certs:/etc/letsencrypt
# command:
# - certonly
# - --standalone
# - --email=admin@sslguard.skyger.cz
# - --agree-tos
# - --no-eff-email
# - -d
# - sslguard.skyger.cz
# - -d
# - api.sslguard.skyger.cz
# ports:
# - "80:80"
db:
image: mariadb:lts
container_name: mariadb
restart: always
environment:
MYSQL_ROOT_PASSWORD: akmf5owtb4yf6r9pbmigr
MYSQL_DATABASE: gsjlqfdaldw08qpihrsax
MYSQL_USER: sslguard-skyger-cz
MYSQL_PASSWORD: gsjlqfdaldw08qpihrsax
volumes:
- ./data/mysql:/var/lib/mysql
ports:
- "127.0.0.1:3306:3306"
- "127.0.0.1:33061:33061"
networks:
- nette-project
haproxy:
image: haproxy:lts
container_name: haproxy
volumes:
- ./haproxy/certs:/usr/local/etc/haproxy/certs/:ro
- ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
ports:
- "80:80"
- "443:443"
- "9000:9000"
depends_on:
- db
- apache
networks:
- nette-project
php-fpm:
build:
context: .
dockerfile: php/Dockerfile
container_name: php
volumes:
- ./app:/domains/sslguard.skyger.cz/
ports:
- "127.0.0.1:9001:9000"
networks:
- nette-project
apache:
build:
context: .
dockerfile: apache/Dockerfile
container_name: apache
ports:
- "127.0.0.1:81:80"
depends_on:
- php-fpm
volumes:
- ./app:/domains/sslguard.skyger.cz/
networks:
- nette-project
keydb:
image: eqalpha/keydb:latest
container_name: keydb
ports:
- "127.0.0.1:6379:6379"
command: keydb-server --appendonly yes
networks:
- nette-project
networks:
nette-project:
driver: bridge
+16
View File
@@ -0,0 +1,16 @@
FROM php:8.4-fpm
RUN apt-get update && \
apt-get install -y git zip unzip libzip-dev && \
docker-php-ext-install zip pdo pdo_mysql
RUN pecl install redis && \
docker-php-ext-enable redis
RUN rm /usr/local/etc/php-fpm.d/*.conf
COPY php/fpm_pool.conf /usr/local/etc/php-fpm.d/sslguard.skyger.cz.conf
# startup.sh
COPY php/startup.sh /usr/local/bin/startup.sh
RUN chmod +x /usr/local/bin/startup.sh
ENTRYPOINT ["/usr/local/bin/startup.sh"]
+20
View File
@@ -0,0 +1,20 @@
[sslguard.skyger.cz]
user = www-data
group = www-data
listen = 9000
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
php_admin_value[open_basedir] = /domains/sslguard.skyger.cz:/data/domains/sslguard.skyger.cz:/tmp
php_admin_value[upload_tmp_dir] = /tmp
php_admin_value[session.save_path] = /tmp
php_admin_flag[display_errors] = off
php_admin_value[error_log] = /domains/sslguard.skyger.cz/_logs/php/php-error.log
php_admin_flag[log_errors] = on
+19
View File
@@ -0,0 +1,19 @@
#!/bin/bash
if [[ -d "/domains/sslguard.skyger.cz/vendor/" ]];
then
exec php-fpm -F;
else
# composer install
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" && \
php composer-setup.php && \
php -r "unlink('composer-setup.php');" && \
mv composer.phar /usr/local/bin/composer;
cd /domains/sslguard.skyger.cz/ && \
composer update;
exec php-fpm -F;
fi;
exit;