RaJiska / BeyondPaste

Online self-hosted pastebin-like tool
BSD 3-Clause "New" or "Revised" License
7 stars 1 forks source link

How to deploy with Apache instead of Nginx? #4

Closed Shushandr closed 1 year ago

Shushandr commented 1 year ago

Yes, Apache is old, but php is not a java-level backend technology too.

# /usr/sbin/apache2ctl -v
Server version: Apache/2.4.57 (Unix)
Server built:   Oct  4 2023 13:51:06
RaJiska commented 1 year ago

Nginx is used as it integrated well with PHP and is a light-weight alternative. I have not used Apache in years since migrating to Nginx, and for the better :). Today I would not know how to configure Apache to work with PHP, let alone replicate the configuration set in the nginx.conf file.

Shushandr commented 1 year ago

I created a database with commands

# mysql
CREATE DATABASE beyondpaste;
CREATE USER 'user'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON beyondpaste.* TO 'user'@'localhost';
# mysql --database=beyondpaste <./config/structure.sql

And I see that user can connect to that database:

# mysql --database=beyondpaste --user=user --password=password 
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 76
Server version: 10.6.14-MariaDB-log Source distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [beyondpaste]> show tables;
+-----------------------+
| Tables_in_beyondpaste |
+-----------------------+
| access                |
| paste                 |
+-----------------------+
2 rows in set (0,000 sec)

I created file `/var/www/localhost/htdocs/.env'.

MYSQL_ROOT_PASSWORD=
MYSQL_DATABASE=beyondpaste
MYSQL_USER=user
MYSQL_PASSWORD=password

I restarted apache with

systemctl restart apache2

but site says "Could not connect to the database"

how to diagnose what was done wrong?

RaJiska commented 1 year ago

Most likely because the .env file is not being parsed. .env is a special file that can be read by docker compose which then passes variable into the container as environment variables.

To solve this, make sure that the user processing PHP files (either the one running the FPM server, or the one running Apache if it executes them directly) have environment variables set for MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD, and MYSQL_HOST. Alternatively, if you do not wish to bother with environment variables, you can directly hardcode those variables here. Beware though that there might be security implications.

As for diagnose issues, you would have to look into Apache and FPM (if you are running it) logs which you might find in /var/log, but can vary depending of your distribution and how you installed those services.

Shushandr commented 1 year ago

I read an article and rewrote web/config/config.php as

<?php

$myEnvDir=__DIR__ . "/";

//echo "\$myEnvDir='" . $myEnvDir . "' ";

$dotenv = Dotenv\Dotenv::createImmutable($myEnvDir, '.env');
$dotenv->load();

$myHost=$_ENV['MYSQL_HOST'];
$myBase=$_ENV['MYSQL_DATABASE'];
$myUser=$_ENV['MYSQL_USER'];
$myPass=$_ENV['MYSQL_PASSWORD'];

// echo "\$myHost='" . $myHost . "' ";
// echo "\$myBase='" . $myBase . "' ";
// echo "\$myUser='" . $myUser . "' ";
// echo "\$myPass='" . $myPass . "' ";

require_once "internal_config.php";

/* Name of the website */
$config['website'] = "BeyondPaste";

/* MySQL DB Credentials */
$config['db']['host'] = $myHost;
$config['db']['name'] = $myBase;
$config['db']['username'] = $myUser;
$config['db']['password'] = $myPass;

also I added line

require __DIR__ . '/vendor/autoload.php';

into /index.php
and I executed

# composer require vlucas/phpdotenv
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Continue as root/super user [yes]? yes
./composer.json has been created
Running composer update vlucas/phpdotenv
Loading composer repositories with package information
Updating dependencies
Lock file operations: 6 installs, 0 updates, 0 removals
  - Locking graham-campbell/result-type (v1.1.1)
  - Locking phpoption/phpoption (1.9.1)
  - Locking symfony/polyfill-ctype (v1.28.0)
  - Locking symfony/polyfill-mbstring (v1.28.0)
  - Locking symfony/polyfill-php80 (v1.28.0)
  - Locking vlucas/phpdotenv (v5.5.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 6 installs, 0 updates, 0 removals
  - Installing symfony/polyfill-php80 (v1.28.0): Extracting archive
  - Installing symfony/polyfill-mbstring (v1.28.0): Extracting archive
  - Installing symfony/polyfill-ctype (v1.28.0): Extracting archive
  - Installing phpoption/phpoption (1.9.1): Extracting archive
  - Installing graham-campbell/result-type (v1.1.1): Extracting archive
  - Installing vlucas/phpdotenv (v5.5.0): Extracting archive
Generating autoload files
6 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
No security vulnerability advisories found.
Using version ^5.5 for vlucas/phpdotenv

sample config doesn't contain variable "MYSQL_HOST", but php file tries to read it. After replacing that line connection was successfull, but I didn't understood why getenv() didn't worked (I replaced it to $_ENV[...] as you can see).

UPD: getenv doesn't work by design - https://github.com/vlucas/phpdotenv/issues/349

RaJiska commented 1 year ago

getenv doesn't work by design - https://github.com/vlucas/phpdotenv/issues/349

To note the .env file was never intended to be anywhere near the document root of your application as this might become a security risk. In the current implementation it is only used by docker compose to be used as environment variable, which $_ENV or getenv() should pick up.

sample config doesn't contain variable "MYSQL_HOST", but php file tries to read it.

It is supplied through docker-compose.yml.

Shushandr commented 1 year ago

I removed everything and redeployed from scratch with the following config fragment:

<Directory "/var/www/localhost/htdocs">
    Options Indexes FollowSymLinks
    DirectoryIndex index.php
    AddType application/x-httpd-php .php
    AddType application/x-httpd-php-source .phps
    AddHandler php5-script .php
    AllowOverride All

    RewriteEngine On
    RewriteRule ^(\w+)/raw$ /index.php?page=raw&pid=$1 [L]
    RewriteRule ^(\w+)$ /index.php?page=view&pid=$1 [L]

    SetEnv MYSQL_HOST "localhost"
    SetEnv MYSQL_DATABASE "beyondpaste"
    SetEnv MYSQL_USER "user"
    SetEnv MYSQL_PASSWORD "password"

    Require all granted
</Directory>

Looks working from the first sight.