# HISTORY ``` 2024-05-24 * init and screen recording /A 2024-11-23 + second instance for InstallAndUse.com /A ``` TODO: - create empty DB ``` db: dox_installanduse_com-bookstack u: dox_installanduse_com-bs_rw p: xxxxxxxxxxxxxxxxxxx ``` - create service account to access bucket ``` bucket: dox_installanduse_com-bookstack user: dox-installanduse-com-bs-rw@projectname-333333.iam.gserviceaccount.com ``` - create a bucket for storage create storage in Cloud Storage, Service account and key-secret pair ``` Name: iau-data-dox Cloud Storage, [create], Region: eu-north1 Choose a storage class for your data [o] Autoclass [x] Opt-in to allow object transitions to Coldline and Archive classes Choose how to control access to objects: Allow public access, [ ] Enforce public access prevention on this bucket Access control: Fine-grained: Object-level ACLs enabled. Cloud storage, Buckets, iau-data-dox, Permissions, [Grant access] New princtipals: dox-installanduse-com-bs-rw@projectname-333333.iam.gserviceaccount.com Storage Legacy Bucket Owner Storage Legacy Bucket Reader Storage Legacy Bucket Writer Storage Legacy Object Owner Storage Legacy Object Reader Storage Object Creator Storage Object User Storage Object Viewer Cloud Storage, Settings, Interoperability, [Create a key for another service account] Service accountName: dox_installanduse_com-bs_rw, [Create key] New key access key and secret will be shown only ONCE. Write it down. dox-installanduse-com-bs-rw@projectname-333333.iam.gserviceaccount.com Access key GOOG1ETE423VPVxxxxxxxxxxxxxxxxxxxxxxxxxxxxxDAO5JMZZA7NKLG4S Secret xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Copy this key's secret if you'll need it in the future. Once you close this dialog, the secret can't be recovered. --or-- Cloud Storage, Settings, Interoperability, [Create a key], Service account HMAC [Create new account] Name: dox_2dz_fi-bookstack, [Create and continue] Roles: Storage Object Admin, [Continue], [Done] Save key and secret! Secret will be shown once. --or-- ``` ```bash gsutil uniformbucketlevelaccess get gs://2dz-data-hub ``` Expected output ```bash Uniform bucket-level access setting for gs://2dz-data-hub: Enabled: False ``` - create CNAME/A record, point to a server ```bash dig A dox.2dz.fi dig A dox.installanduse.com +short ``` - create home directory for application ```bash whoami sudo su # privileged user (you) export pu="anton" # working directory (for easy future maintenance) export wd="/var/www/dox.installanduse.com" mkdir -p ${wd} # permit priviledged user to own app directory chown -R ${pu}:${pu} ${wd} exit # as priviledged user, not as root export wd="/var/www/dox.installanduse.com" cd ${wd} ``` clone latest application source code from repo ```bash git clone https://github.com/BookStackApp/BookStack.git --branch release --single-branch ls -la BookStack/ ``` Download composer and install in global mode (as normal user, not as root), later easy to update. ```bash mkdir -p ~/utils/composer cd ~/utils/composer/ php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" php -r "if (hash_file('sha384', 'composer-setup.php') === 'dac665fdc30fdd8ec78b38b9800061b4150413ff2e3b6f88543c636f7cd84f6db9189d43a81e5503cda447da73c7e5b6') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" php composer-setup.php php -r "unlink('composer-setup.php');" php composer.phar sudo mv composer.phar /usr/local/bin/composer ``` - build (composer install) ```bash cd ${wd}/BookStack which composer composer install --no-dev ``` Set least necessary permissions for webserver ```bash sudo su export wd="/var/www/dox.installanduse.com" # webserver's user export wsu="www-data" chown -R ${wsu}:${wsu} ${wd}/BookStack/storage/ chmod -R 775 ${wd}/BookStack/storage/ chown -R ${wsu}:${wsu} ${wd}/BookStack/bootstrap/cache/ chmod -R 775 ${wd}/BookStack/bootstrap/cache/ chown -R ${wsu}:${wsu} ${wd}/BookStack/public/uploads/ chmod -R 775 ${wd}/BookStack/public/uploads/ chown -R ${wsu}:${wsu} ${wd}/BookStack/public/ ``` Copy template, generate salt abd configure .env ```bash cp .env.example .env php artisan key:generate vi .env ``` ``` APP_KEY=base64:xxxxxxxxxxxxxxxxxxxxxxxxPbw8= APP_URL=https://dox.installanduse.com DB_HOST=172.21.xx.xx DB_DATABASE=dox_installanduse_com-bookstack DB_USERNAME=dox_installanduse_com-bs_rw DB_PASSWORD=xxxxxxxxxxxxxxxxxxx MAIL_DRIVER=smtp MAIL_FROM_NAME="dox.installanduse.com" MAIL_FROM=dox@installanduse.com MAIL_HOST=127.0.0.1 MAIL_PORT=25 MAIL_USERNAME=null MAIL_PASSWORD=null MAIL_ENCRYPTION=null MAIL_VERIFY_SSL=false STORAGE_TYPE=s3 STORAGE_S3_KEY=GOOG1ETE423VPVUU3PBHxxxxxxxxxxxxxxxNZD3B4YDAO5JMZZA7NKLG4S STORAGE_S3_SECRET=4mUF0niGoHfenkxxxxxxxxxxxZCoUqCIiwpg89Evj STORAGE_S3_BUCKET=iau-data-dox STORAGE_S3_REGION=europe-north1 STORAGE_S3_ENDPOINT=https://storage.googleapis.com STORAGE_URL=https://storage.googleapis.com/iau-data-dox ``` # Configure webserver (nginx) create site config. Determine, where is PHP is listening to. It is very important, as I spent many hours many years ago to figure out, troubleshooting it. There are two ways to find the answer. You should use the most generic one, because after version upgrade, confgiration will remain functional. ```bash sudo su systemctl | grep php systemctl status php8.2-fpm.service less /lib/systemd/system/php8.2-fpm.service # observe for socket path ls -la /run/php/php-fpm.sock ``` ```bash lrwxrwxrwx 1 root root 30 May 23 00:21 /run/php/php-fpm.sock -> /etc/alternatives/php-fpm.sock ``` ```bash ls -la /etc/alternatives/php-fpm.sock ```bash lrwxrwxrwx 1 root root 24 May 23 00:21 /etc/alternatives/php-fpm.sock -> /run/php/php8.2-fpm.sock ``` ```bash ls -la /run/php/php8.2-fpm.sock ``` ```bash srw-rw---- 1 www-data www-data 0 May 23 00:21 /run/php/php8.2-fpm.sock ``` Or check via configuration ```bash fgrep -irn fpm.sock /etc/php/ ``` Determine from output location of socket ```bash /etc/php/8.2/fpm/pool.d/www.conf:41:listen = /run/php/php8.2-fpm.sock ``` To summarize own findings, we shall use: ```bash /run/php/php-fpm.sock ``` ```bash sudo su # copy output of root path echo ${wd}/BookStack/public cd /etc/nginx/sites-available vi dox.installanduse.com.conf ``` Create a simple virtualhost configuration listining on http. SSL will be enabled later by CertBot. ```ini server { listen 80; listen [::]:80; server_name dox.installanduse.com; root /var/www/dox.installanduse.com/BookStack/public; index index.php index.html; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php-fpm.sock; } } ``` - enable available site ```bash ln -s /etc/nginx/sites-available/dox.installanduse.com.conf /etc/nginx/sites-enabled/ ls -latr /etc/nginx/sites-enabled ``` Test webserver configuration, and reload it. ```bash nginx -t nginx -s reload # systemctl restart nginx ss -ntap | grep nginx ``` - upgrade DB (recreate/upgrade schema to the recent), approve warning on application in production (we are doing fresh deployment) ```bash exit id export wd="/var/www/dox.installanduse.com" cd ${wd}/BookStack php artisan migrate ``` Check DB ```bash mysql -h (dbhost) -u dox_installanduse_com-bs_rw -p ``` ```sql MySQL [(none)]> SHOW DATABASES; [...] | dox_installanduse_com-bookstack | [...] MySQL [(none)]> USE dox_installanduse_com-bookstack; [...] Database changed MySQL [dox_installanduse_com-bookstack]> SHOW TABLES; [...] | users | [...] +-------------------------------------------+ 38 rows in set (0.003 sec) MySQL [dox_installanduse_com-bookstack]> SELECT * FROM users; [...] | 1 | Admin | admin@admin.com | $2y$12$Hw/USVgBnbR2OEuSSaxxxxxxxxxxbPLUFcw8n98xjK.MP45K | NULL | 2024-11-23 16:30:10 | 2024-11-23 16:30:10 | 1 | 0 | | NULL | admin | [...] 2 rows in set (0.003 sec) quit ``` After DB is built, main page of application should be accessible over HTTP, it will be automatically redirected to HTTPS and will not be possible to view via browser. But from CLI, it will be possible using curl: ```bash curl http://dox.installanduse.com ``` ```bash