mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-08-26 12:46:08 +00:00
nextcloud: Use php-fpm container instead of apache container
- Configuring just php-fpm is easier compared to configuring Apache + mod_php. There is no need to configure trusted proxies as the requests are made using the FastCGI protocol. - There is no need for a full web server as we already run Apache. - Place nextcloud data in /var/lib/container so that non-PHP files can be served directly without php-fpm involved. This location is more suitable for switching to nextcloud based on a .deb file (if ever). This is done by configuring the volume to serve a bind mounted directory of our choice. - Update Apache configuration to proxy to php-fpm instead of another web server. Include the changes needed for Apache configuration to serve non-php files directly. - Managed the volume using quadlet podman systemd generator. Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
e7e1a6b41d
commit
85cc9f08fa
@ -489,22 +489,44 @@ def is_package_manager_busy():
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def podman_create(container_name: str, image_name: str,
|
def podman_create(container_name: str, image_name: str, volume_name: str,
|
||||||
volumes: dict[str, str] | None = None,
|
volume_path: str, volumes: dict[str, str] | None = None,
|
||||||
env: dict[str, str] | None = None):
|
env: dict[str, str] | None = None):
|
||||||
"""Remove and recreate a podman container."""
|
"""Remove and recreate a podman container."""
|
||||||
|
service_stop(f'{volume_name}-volume.service')
|
||||||
service_stop(container_name)
|
service_stop(container_name)
|
||||||
|
|
||||||
directory = pathlib.Path('/etc/containers/systemd')
|
directory = pathlib.Path('/etc/containers/systemd')
|
||||||
directory.mkdir(parents=True, exist_ok=True)
|
directory.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
subprocess.run(['podman', 'volume', 'rm', '--force', volume_name],
|
||||||
|
check=False)
|
||||||
|
|
||||||
|
directory = pathlib.Path('/etc/containers/systemd')
|
||||||
|
directory.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
pathlib.Path(volume_path).mkdir(parents=True, exist_ok=True)
|
||||||
|
# Create storage volume
|
||||||
|
volume_file = directory / f'{volume_name}.volume'
|
||||||
|
contents = f'''[Volume]
|
||||||
|
Device={volume_path}
|
||||||
|
Driver=local
|
||||||
|
VolumeName={volume_name}
|
||||||
|
Options=bind
|
||||||
|
'''
|
||||||
|
volume_file.write_text(contents)
|
||||||
|
|
||||||
service_file = directory / f'{container_name}.container'
|
service_file = directory / f'{container_name}.container'
|
||||||
volume_lines = '\n'.join([
|
volume_lines = '\n'.join([
|
||||||
f'Volume={source}:{dest}' for source, dest in (volumes or {}).items()
|
f'Volume={source}:{dest}' for source, dest in (volumes or {}).items()
|
||||||
])
|
])
|
||||||
env_lines = '\n'.join(
|
env_lines = '\n'.join(
|
||||||
[f'Environment={key}={value}' for key, value in (env or {}).items()])
|
[f'Environment={key}={value}' for key, value in (env or {}).items()])
|
||||||
contents = f'''[Container]
|
contents = f'''[Unit]
|
||||||
|
Requires=nextcloud-freedombox-volume.service
|
||||||
|
After=nextcloud-freedombox-volume.service
|
||||||
|
|
||||||
|
[Container]
|
||||||
AutoUpdate=registry
|
AutoUpdate=registry
|
||||||
ContainerName=%N
|
ContainerName=%N
|
||||||
{env_lines}
|
{env_lines}
|
||||||
@ -522,11 +544,18 @@ WantedBy=default.target
|
|||||||
service_daemon_reload()
|
service_daemon_reload()
|
||||||
|
|
||||||
|
|
||||||
def podman_uninstall(container_name: str, volume_name: str, image_name: str):
|
def podman_uninstall(container_name: str, volume_name: str, image_name: str,
|
||||||
|
volume_path: str):
|
||||||
"""Remove a podman container's components and systemd unit."""
|
"""Remove a podman container's components and systemd unit."""
|
||||||
subprocess.run(['podman', 'volume', 'rm', volume_name], check=True)
|
subprocess.run(['podman', 'volume', 'rm', '--force', volume_name],
|
||||||
subprocess.run(['podman', 'image', 'rm', image_name], check=True)
|
check=True)
|
||||||
|
subprocess.run(['podman', 'image', 'rm', '--ignore', image_name],
|
||||||
|
check=True)
|
||||||
|
volume_file = pathlib.Path(
|
||||||
|
'/etc/containers/systemd/') / f'{volume_name}.volume'
|
||||||
|
volume_file.unlink(missing_ok=True)
|
||||||
service_file = pathlib.Path(
|
service_file = pathlib.Path(
|
||||||
'/etc/containers/systemd/') / f'{container_name}.container'
|
'/etc/containers/systemd/') / f'{container_name}.container'
|
||||||
service_file.unlink(missing_ok=True)
|
service_file.unlink(missing_ok=True)
|
||||||
|
shutil.rmtree(volume_path, ignore_errors=True)
|
||||||
service_daemon_reload()
|
service_daemon_reload()
|
||||||
|
|||||||
@ -87,7 +87,7 @@ class NextcloudApp(app_module.App):
|
|||||||
self.add(firewall)
|
self.add(firewall)
|
||||||
|
|
||||||
firewall_local_protection = FirewallLocalProtection(
|
firewall_local_protection = FirewallLocalProtection(
|
||||||
'firewall-local-protection-nextcloud', ['8181'])
|
'firewall-local-protection-nextcloud', ['9000'])
|
||||||
self.add(firewall_local_protection)
|
self.add(firewall_local_protection)
|
||||||
|
|
||||||
webserver = Webserver('webserver-nextcloud', 'nextcloud-freedombox',
|
webserver = Webserver('webserver-nextcloud', 'nextcloud-freedombox',
|
||||||
|
|||||||
@ -16,10 +16,36 @@ Redirect 301 /.well-known/caldav /nextcloud/remote.php/dav
|
|||||||
Redirect 301 /.well-known/webfinger /nextcloud/index.php/.well-known/webfinger
|
Redirect 301 /.well-known/webfinger /nextcloud/index.php/.well-known/webfinger
|
||||||
Redirect 301 /.well-known/nodeinfo /nextcloud/index.php/.well-known/nodeinfo
|
Redirect 301 /.well-known/nodeinfo /nextcloud/index.php/.well-known/nodeinfo
|
||||||
|
|
||||||
<Location /nextcloud>
|
Alias /nextcloud/ /var/lib/nextcloud/
|
||||||
ProxyPass http://127.0.0.1:8181
|
|
||||||
|
|
||||||
## Send the scheme from user's request to enable Nextcloud to redirect URLs,
|
<IfModule proxy_fcgi_module>
|
||||||
## set cookies, set absolute URLs (if any) properly.
|
ProxyPassMatch "^/nextcloud/(.*\.php(/.*)?)$" "fcgi://localhost:9000/var/www/html/$1"
|
||||||
RequestHeader set X-Forwarded-Proto 'https' env=HTTPS
|
</IfModule>
|
||||||
</Location>
|
|
||||||
|
<Directory /var/lib/nextcloud/>
|
||||||
|
<IfModule !mod_php7.c>
|
||||||
|
<IfModule proxy_fcgi_module>
|
||||||
|
# Enable http authorization headers
|
||||||
|
<IfModule setenvif_module>
|
||||||
|
SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
<FilesMatch ".+\.phps$">
|
||||||
|
# Deny access to raw php sources by default
|
||||||
|
# To re-enable it's recommended to enable access to the files
|
||||||
|
# only in specific virtual host or directory
|
||||||
|
Require all denied
|
||||||
|
</FilesMatch>
|
||||||
|
# Deny access to files without filename (e.g. '.php')
|
||||||
|
<FilesMatch "^\.ph(ar|p|ps|tml)$">
|
||||||
|
Require all denied
|
||||||
|
</FilesMatch>
|
||||||
|
</IfModule>
|
||||||
|
</IfModule>
|
||||||
|
|
||||||
|
Require all granted
|
||||||
|
|
||||||
|
# Allow a limited set of directives in .htaccess files found in /, /config,
|
||||||
|
# and /data directories of nextcloud.
|
||||||
|
AllowOverride AuthConfig FileInfo Indexes Limit Options
|
||||||
|
</Directory>
|
||||||
|
|||||||
@ -48,9 +48,7 @@ clients = [{
|
|||||||
|
|
||||||
backup = {
|
backup = {
|
||||||
'data': {
|
'data': {
|
||||||
'directories': [
|
'directories': ['/var/lib/nextcloud/'],
|
||||||
'/var/lib/containers/storage/volumes/nextcloud-volume-freedombox/'
|
|
||||||
],
|
|
||||||
'files': ['/var/lib/plinth/backups-data/nextcloud-database.sql']
|
'files': ['/var/lib/plinth/backups-data/nextcloud-database.sql']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,8 +17,8 @@ from plinth.actions import privileged
|
|||||||
|
|
||||||
CONTAINER_NAME = 'nextcloud-freedombox'
|
CONTAINER_NAME = 'nextcloud-freedombox'
|
||||||
SERVICE_NAME = 'nextcloud-freedombox'
|
SERVICE_NAME = 'nextcloud-freedombox'
|
||||||
VOLUME_NAME = 'nextcloud-volume-freedombox'
|
VOLUME_NAME = 'nextcloud-freedombox'
|
||||||
IMAGE_NAME = 'docker.io/library/nextcloud:stable-apache'
|
IMAGE_NAME = 'docker.io/library/nextcloud:stable-fpm'
|
||||||
|
|
||||||
DB_HOST = 'localhost'
|
DB_HOST = 'localhost'
|
||||||
DB_NAME = 'nextcloud_fbx'
|
DB_NAME = 'nextcloud_fbx'
|
||||||
@ -26,8 +26,7 @@ DB_USER = 'nextcloud_fbx'
|
|||||||
GUI_ADMIN = 'nextcloud-admin'
|
GUI_ADMIN = 'nextcloud-admin'
|
||||||
REDIS_DB = 8 # Don't clash with other redis apps
|
REDIS_DB = 8 # Don't clash with other redis apps
|
||||||
|
|
||||||
_volume_path = pathlib.Path(
|
_data_path = pathlib.Path('/var/lib/nextcloud/')
|
||||||
'/var/lib/containers/storage/volumes/') / VOLUME_NAME
|
|
||||||
_systemd_location = pathlib.Path('/etc/systemd/system/')
|
_systemd_location = pathlib.Path('/etc/systemd/system/')
|
||||||
_cron_service_file = _systemd_location / 'nextcloud-cron-freedombox.service'
|
_cron_service_file = _systemd_location / 'nextcloud-cron-freedombox.service'
|
||||||
_cron_timer_file = _systemd_location / 'nextcloud-cron-freedombox.timer'
|
_cron_timer_file = _systemd_location / 'nextcloud-cron-freedombox.timer'
|
||||||
@ -55,16 +54,18 @@ def setup():
|
|||||||
'/run/slapd/ldapi': '/run/slapd/ldapi',
|
'/run/slapd/ldapi': '/run/slapd/ldapi',
|
||||||
VOLUME_NAME: '/var/www/html'
|
VOLUME_NAME: '/var/www/html'
|
||||||
}
|
}
|
||||||
env = {'TRUSTED_PROXIES': '127.0.0.1', 'OVERWRITEWEBROOT': '/nextcloud'}
|
env = {'OVERWRITEWEBROOT': '/nextcloud'}
|
||||||
action_utils.podman_create(container_name=CONTAINER_NAME,
|
action_utils.podman_create(container_name=CONTAINER_NAME,
|
||||||
image_name=IMAGE_NAME, volumes=volumes, env=env)
|
image_name=IMAGE_NAME, volume_name=VOLUME_NAME,
|
||||||
|
volume_path=str(_data_path), volumes=volumes,
|
||||||
|
env=env)
|
||||||
action_utils.service_start(CONTAINER_NAME)
|
action_utils.service_start(CONTAINER_NAME)
|
||||||
|
|
||||||
# OCC isn't immediately available after the container is spun up.
|
# OCC isn't immediately available after the container is spun up.
|
||||||
# Wait until CAN_INSTALL file is available.
|
# Wait until CAN_INSTALL file is available.
|
||||||
timeout = 300
|
timeout = 300
|
||||||
while timeout > 0:
|
while timeout > 0:
|
||||||
if (_volume_path / '_data/config/CAN_INSTALL').exists():
|
if (_data_path / 'config/CAN_INSTALL').exists():
|
||||||
break
|
break
|
||||||
|
|
||||||
timeout = timeout - 1
|
timeout = timeout - 1
|
||||||
@ -278,7 +279,8 @@ def uninstall():
|
|||||||
_drop_database()
|
_drop_database()
|
||||||
action_utils.podman_uninstall(container_name=CONTAINER_NAME,
|
action_utils.podman_uninstall(container_name=CONTAINER_NAME,
|
||||||
volume_name=VOLUME_NAME,
|
volume_name=VOLUME_NAME,
|
||||||
image_name=IMAGE_NAME)
|
image_name=IMAGE_NAME,
|
||||||
|
volume_path=str(_data_path))
|
||||||
for path in [_cron_service_file, _cron_timer_file]:
|
for path in [_cron_service_file, _cron_timer_file]:
|
||||||
path.unlink(missing_ok=True)
|
path.unlink(missing_ok=True)
|
||||||
|
|
||||||
@ -366,7 +368,7 @@ def _get_dbpassword():
|
|||||||
|
|
||||||
def _create_redis_config():
|
def _create_redis_config():
|
||||||
"""Create a php file for Redis configuration."""
|
"""Create a php file for Redis configuration."""
|
||||||
config_file = _volume_path / '_data/config/freedombox.config.php'
|
config_file = _data_path / 'config/freedombox.config.php'
|
||||||
file_content = fr'''<?php
|
file_content = fr'''<?php
|
||||||
$CONFIG = [
|
$CONFIG = [
|
||||||
'memcache.distributed' => '\OC\Memcache\Redis',
|
'memcache.distributed' => '\OC\Memcache\Redis',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user