Commits (738)
......@@ -19,7 +19,11 @@ build/
......@@ -28,11 +32,16 @@ plinth/tests/coverage/report/
......@@ -7,7 +7,7 @@ before_script:
- apt-get install -y build-essential # Build dependencies
- apt-get install -y sshpass parted # Test dependencies
- apt-get install -y sudo
- apt-get remove -y python3.7* libpython3.7* # Use python3.6 when installing dependencies
- apt-mark hold fuse fuse3 # not installable in CI environment
- apt-get install -y $(./run --list-dependencies) # Module dependencies
......@@ -17,14 +17,14 @@ stages:
stage: test
- apt-get install -y python3-coverage
- adduser tester --gecos "First Last,RoomNumber,WorkPhone,HomePhone" --disabled-password
- echo "tester:password" | chpasswd
- cp -r . /home/tester/plinth
- chown -R tester:tester /home/tester/plinth
- su -c "cd ~/plinth; python3 setup.py test_coverage" tester
- cp -r /home/tester/plinth/plinth/tests/coverage/report test-coverage-report
- su -c "cd ~/plinth; py.test-3 --cov=plinth --cov-report=html --cov-report=term" tester
- cp -r /home/tester/plinth/htmlcov test-coverage-report
coverage: '/^TOTAL\s+.*\s+(\d+\.\d+%)$/'
- test-coverage-report/*
......@@ -32,10 +32,9 @@ run-unit-tests:
stage: package
- apt-get build-dep -y . # Re-install python3.7 again
- DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -us -uc -b
- mkdir debian-package
- mv ../plinth*.deb debian-package
- mv ../freedombox*.deb debian-package
......@@ -13,7 +13,7 @@ Naming conventions:
* 'Code change', 'patch', and 'commit' are used interchangeably.
* 'Author' and 'contributor' are used interchangeably.
* Git 'log' and 'history' are used interchangeably.
* PR - pull request
* PR, MR - pull request and merge request, used interchangeably.
* 'Merging' often means 'applying a patch to git history' in a general sense,
not literal execution of the command `git merge`.
......@@ -49,6 +49,8 @@ Naming conventions:
to a [Developer Certificate of Origin](http://developercertificate.org/).
* If (part of) your code changes were inspired or plainly copied from another
source, please indicate this in the PR, so the reviewer can handle it.
* If your PR is not ready for merging yet, the title of your PR must start with
* Have fun contributing :)
......@@ -82,6 +84,9 @@ Naming conventions:
* In case more fundamental changes are necessary, or if the contributor is new,
try to encourage them to make changes by giving appropriate feedback. This is
a major way how we mentor new contributors.
* Any PR whose title starts with `WIP:` cannot be merged. Communicate with the
author on what the pending changes are. Get the author to complete them or
complete them yourself in case of an emergency.
* Have fun reviewing :)
# License to Copy FreedomBox Service (Plinth)
FreedomBox Service (Plinth) is Copyright 2011, 2012, 2013, 2014, 2015, 2016,
2017, 2018 FreedomBox Authors. See Git log in the source repository for a full
list of authors. It is distributed under the GNU Affero General Public License,
Version 3 or later. A copy of AGPLv3 is available [from the Free Software
FreedomBox Service (Plinth) is Copyright 2011, 2012, 2013, 2014, 2015,
2016, 2017, 2018, 2019 FreedomBox Authors. See Git log in the source
repository for a full list of authors. It is distributed under the GNU
Affero General Public License, Version 3 or later. A copy of AGPLv3 is
available [from the Free Software
In addition, the documentation to this software is distributed under a
......@@ -18,6 +18,7 @@ and requires about 4.5 GB of disk space.
2. To download, setup, run, and configure a VM for FreedomBox development using
Vagrant, simply execute in your FreedomBox Service (Plinth) development
$ vagrant up
......@@ -31,28 +32,33 @@ and requires about 4.5 GB of disk space.
virtual machine using the following command. This command continuously
deploys your code changes into the virtual machine providing a quick feedback
cycle during development.
$ sudo /vagrant/run --develop
$ sudo -u plinth /vagrant/run --develop
Note: This virtual machine has automatic upgrades disabled by default.
## Installing Dependencies
Apart from dependencies listing in INSTALL.md file, there may be additional
dependencies required by apps of FreedomBox. To install these, run:
$ sudo apt install -y $(plinth --list-dependencies)
## Manually Setting Up for Development
It is recommended that you use Vagrant to setup your development environment.
However, for some reason, you wish setup manually, the following tips will help:
1. Instead of running `setup.py install` after every source modification, run
1. Install dependencies as follows:
$ sudo apt build-dep .
$ sudo apt install -y $(./run --list-dependencies)
Install additional dependencies by picking the list from debian/control file
fields Depends: and Recommends: for the package ''freedombox''.
2. Instead of running `setup.py install` after every source modification, run
the following command:
......@@ -109,23 +115,32 @@ However, for some reason, you wish setup manually, the following tips will help:
To run all the tests:
$ python3 setup.py test
$ py.test-3
To run a specific test function, test class or test module, use the `-s` option
with the fully qualified name.
Another way to run tests (not recommended):
$ ./setup.py test
To run a specific test function, test class or test module, use pytest filtering
# Run tests of a test module
$ python3 setup.py test -s plinth.tests.test_actions
# Run tests in a directory
$ py.test-3 plinth/tests
# Run tests in a module
$ py.test-3 plinth/tests/test_actions.py
# Run tests of one class in test module
$ python3 setup.py test -s plinth.tests.test_actions.TestActions
$ py.test-3 plinth/tests/test_actions.py::TestActions
# Run one test in a class or module
$ python3 setup.py test -s plinth.tests.test_actions.TestActions.test_is_package_manager_busy
$ py.test-3 plinth/tests/test_actions.py::TestActions::test_is_package_manager_busy
## Running the Test Coverage Analysis
......@@ -133,20 +148,95 @@ $ python3 setup.py test -s plinth.tests.test_actions.TestActions.test_is_package
To run the coverage tool:
$ python3 setup.py test_coverage
$ py.test-3 --cov=plinth
To collect HTML report:
$ py.test-3 --cov=plinth --cov-report=html
Invoking this command generates a binary-format `.coverage` data file in
the top-level project directory which is recreated with each run, and
writes a set of HTML and other supporting files which comprise the
browsable coverage report to the `plinth/tests/coverage/report` directory.
`Index.html` presents the coverage summary, broken down by module. Data
columns can be sorted by clicking on the column header or by using mnemonic
hot-keys specified in the keyboard widget in the upper-right corner of the
page. Clicking on the name of a particular source file opens a page that
displays the contents of that file, with color-coding in the left margin to
indicate which statements or branches were executed via the tests (green)
and which statements or branches were not executed (red).
Invoking this command generates a HTML report to the `htmlcov` directory.
`index.html` presents the coverage summary, broken down by module. Data columns
can be sorted by clicking on the column header. Clicking on the name of a
particular source file opens a page that displays the contents of that file,
with color-coding in the left margin to indicate which statements or branches
were executed via the tests (green) and which statements or branches were not
executed (red).
## Running Functional Tests
### Install Dependencies
**For running tests in the VM** run `vagrant provision --provision-with tests`.
Otherwise follow the instructions below.
$ pip3 install splinter
$ pip3 install pytest-splinter
$ pip3 install pytest-bdd
$ sudo apt install xvfb # optional, to avoid opening browser windows
$ pip3 install pytest-xvfb # optional, to avoid opening browser windows
- Install the latest version of geckodriver.
It's usually a single binary which you can place at /usr/local/bin/geckodriver
- Install the latest version of Mozilla Firefox.
Download and extract the latest version from the Firefox website and symlink the
binary named `firefox` to /usr/local/bin.
Geckodriver will then use whatever version of Firefox you symlink as
### Run FreedomBox Service
*Warning*: Functional tests will change the configuration of the system
under test, including changing the hostname and users. Therefore you
should run the tests using FreedomBox running on a throw-away VM.
The VM should have NAT port-forwarding enabled so that 4430 on the
host forwards to 443 on the guest. From where the tests are running, the web
interface of FreedomBox should be accessible at https://localhost:4430/.
### Setup FreedomBox Service for tests
Via Plinth, create a new user as follows:
* Username: tester
* Password: testingtesting
This step is optional if a fresh install of Plinth is being tested. Functional
tests will create the required user using FreedomBox's first boot process.
### Run Functional Tests
**When inside a VM you will need to target the guest VM**
export FREEDOMBOX_URL=https://localhost
You will be running `py.test-3`.
$ py.test-3 --include-functional
The full test suite can take a long time to run (more than an hour). You can
also specify which tests to run, by tag or keyword:
$ py.test-3 -k essential --include-functional
If xvfb is installed and you still want to see browser windows, use the
`--no-xvfb` command-line argument.
$ py.test-3 --no-xvfb -k mediawiki --include-functional
## Building the Documentation Separately
# Installing FreedomBox Service (Plinth)
1. Install the dependencies:
The following instructions are for installing FreedomBox from source code meant
for advanced users. For regular use of FreedomBox, instructions are available on
FreedomBox [Manual](https://wiki.debian.org/FreedomBox/Manual/)'s
[QuickStart](https://wiki.debian.org/FreedomBox/Manual/QuickStart) page.
On a Debian based system, run:
1. Install FreedomBox Service (Plinth):
A Debian based system is needed to run FreedomBox. Buster release or later
is recommended. Unzip the source into a directory. Change to the directory
containing the program and run:
$ sudo apt-get install \
augeas-tools \
dblatex \
docbook-utils \
e2fsprogs \
fonts-lato \
gettext \
gir1.2-glib-2.0 \
gir1.2-nm-1.0 \
ldapscripts \
libjs-bootstrap \
libjs-jquery \
libjs-modernizr \
make \
network-manager \
ppp \
pppoe \
python3 \
python3-apt \
python3-augeas \
python3-bootstrapform \
python3-cherrypy3 \
python3-configobj \
python3-coverage \
python3-django \
python3-django-axes \
python3-django-captcha \
python3-django-stronghold \
python3-gi \
python3-psutil \
python3-requests \
python3-ruamel.yaml \
python3-setuptools \
$ sudo apt build-dep .
2. Install FreedomBox Service (Plinth):
$ sudo apt install -y $(./run --list-dependencies)
Unzip the source into a directory. Change to the directory containing the
program and run:
Install additional dependencies by picking the list from debian/control file
fields Depends: and Recommends: for the package ''freedombox''. After that
install FreedomBox Service (Plinth) itself.
$ sudo python3 setup.py install
$ sudo apt install -y $(plinth --list-dependencies)
3. Run FreedomBox Service (Plinth):
2. Run FreedomBox Service (Plinth):
$ sudo plinth
4. Access FreedomBox UI:
3. Access FreedomBox UI:
UI should be accessible at http://localhost:8000/plinth
# Note on Django version:
Django 1.11 is required to run FreedomBox Service (Plinth). You can check the
version by running:
$ django-admin --version
If apt-get provided django < 1.11, then follow the steps below:
1. Uninstall older django versions:
$ sudo apt-get remove python3-django python3-django-stronghold \
2. Install Python3 pip:
$ sudo apt-get install python3-pip
3. Install django1.11 through pip:
$ sudo pip3 install django django-bootstrap-form django-stronghold \
django-axes django-simple-captcha --upgrade
If you are installing FreedomBox Service (Plinth) for development purposes, see
HACKING.md instead.
# -*- mode: org; mode: org-indent; mode: visual-line; -*-
Files containing license headers are not listed here. For each of the
files listed, the copyright specified for the file is listed. "-" means
"no license specified in the file," licenses are specified and linked
License for this program is described in COPYING.md. Individual files with
different licenses are primarily listed in debian/copyright. The remaining are
listed here.
- HACKING :: -
- INSTALL :: -
- plinth.config :: -
- README :: -
- data/etc/apache2/plinth.conf :: -
- data/etc/apache2/plinth-ssl.conf :: -
- data/etc/sudoers.d/plinth :: -
- static/themes/default/FreedomBox-Identity-Manual.pdf :: -
- static/themes/default/FreedomBox-Logo.7z :: [[http://thread.gmane.org/gmane.linux.debian.freedombox.user/4124/focus=4439][GPL3+/CC-BY-SA]]
- static/themes/default/readme.md :: [[file:themes/default/readme.md::This%20theme%20is%20free%20software%20offered%20to%20you%20under%20the%20terms%20of%20the%20GNU%20Affero%20General%20Public%20License,%20Version%203%20or%20later:][GNU Affero General Public License Version 3]]
- static/themes/default/screenshot.png :: -
- static/themes/default/img/apple-touch-icon-114px-precomposed.png :: -
- static/themes/default/img/apple-touch-icon-57px-precomposed.png :: -
- static/themes/default/img/apple-touch-icon-72px-precomposed.png :: -
- static/themes/default/img/apple-touch-icon.xcf :: -
- static/themes/default/img/freedombox-logo-200px.png :: -
- static/themes/default/img/freedombox-logo-250px.png :: -
- static/themes/default/img/freedombox-logo-32px.png :: -
- static/themes/default/img/FreedomBox-logo-grayscale-negative.png :: -
- static/themes/default/img/FreedomBox-logo-grayscale-negative.svg :: -
- static/themes/default/img/FreedomBox-logo-grayscale.png :: -
- static/themes/default/img/FreedomBox-logo-grayscale.svg :: -
- static/themes/default/img/FreedomBox-logo-lineart-negative.png :: -
- static/themes/default/img/FreedomBox-logo-lineart-negative.svg :: -
- static/themes/default/img/FreedomBox-logo-lineart.png :: -
- static/themes/default/img/FreedomBox-logo-lineart.svg :: -
- static/themes/default/img/FreedomBox-logo-standard.png :: -
- static/themes/default/img/FreedomBox-logo-standard.svg :: -
- static/themes/default/img/freedombox-logotype.png :: -
- static/themes/default/img/network-computer.svg :: [[https://commons.wikimedia.org/wiki/File:Gnome-computer.svg][LGPLv3+]]
- static/themes/default/img/network-connection.svg :: [[http://tango.freedesktop.org/][Public Domain]]
- static/themes/default/img/network-connection-vertical.svg :: [[http://tango.freedesktop.org/][Public Domain]]
- static/themes/default/img/network-ethernet.svg :: [[http://tango.freedesktop.org/][Public Domain]]
- static/themes/default/img/network-freedombox.svg :: [[http://thread.gmane.org/gmane.linux.debian.freedombox.user/4124/focus=4439][GPL3+/CC-BY-SA]]
- static/themes/default/img/network-internet.svg :: [[http://tango.freedesktop.org/][Public Domain]]
- static/themes/default/img/network-wireless.svg :: [[http://tango.freedesktop.org/][Public Domain]]
- static/themes/default/icons/deluge.png :: [[https://upload.wikimedia.org/wikipedia/commons/thumb/8/85//Deluge-Logo.svg/2000px-Deluge-Logo.svg.png][GPL]]
- static/themes/default/icons/diaspora.png :: [[https://upload.wikimedia.org/wikipedia/commons/thumb/8/85//Deluge-Logo.svg/2000px-Deluge-Logo.svg.png][Publc Domain]]
- static/themes/default/icons/ejabberd.png :: [[https://www.ejabberd.im/][GPL-2]]
- static/themes/default/icons/infinoted.png :: [[https://github.com/gobby/gobby/blob/master/COPYING][ISC]]
- static/themes/default/icons/ikiwiki.png :: [[https://ikiwiki.info/][GPL-2+]]
- static/themes/default/icons/jsxc.png :: -
- static/themes/default/icons/matrixsynapse.png :: [[https://github.com/thekishanraval/Logos][GPLv3+]]
- static/themes/default/icons/minetest.png :: [[http://www.minetest.net/media/icon.svg][LGPL 2.1]]
- static/themes/default/icons/mumble.png :: [[https://commons.wikimedia.org/wiki/File:Icons_mumble.svg][BSD-3-clause]]
- static/themes/default/icons/openvpn.png :: [[https://github.com/thekishanraval/Logos][GPLv3+]]
- static/themes/default/icons/privoxy.png :: [[https://openhub.net/p/privoxy][GPL]]
- static/themes/default/icons/quassel.png :: [[http://quassel-irc.org/][GPL-3]]
- static/themes/default/icons/radicale.png :: [[http://radicale.org/][GPL-3.0]]
- static/themes/default/icons/repro.png :: [[https://www.resiprocate.org/Main_Page][BSD-3-clause]]
- static/themes/default/icons/roundcube.png :: [[https://roundcube.net/][GPL-3+]]
- static/themes/default/icons/shaarli.png :: [[https://github.com/shaarli/Shaarli][zlib/libpng]]
- static/themes/default/icons/shadowsocks.png :: [[https://commons.wikimedia.org/wiki/File:Shadowsocks_logo.png][Apache 2.0]]
- static/themes/default/icons/sharing.png :: [[https://www.shareicon.net/social-share-this-107338][CC 2.5]]
- static/themes/default/icons/syncthing.png :: [[https://github.com/syncthing/syncthing/][Mozilla Public License Version 2.0]]
- static/themes/default/icons/tahoe.png :: [[https://github.com/thekishanraval/Logos][GPLv3+]]
- static/themes/default/icons/tor.png :: [[https://commons.wikimedia.org/wiki/File:Tor_logo1.png][CC BY 3.0 US]]
- static/themes/default/icons/transmission.png :: [[https://transmissionbt.com/][GPL]]
- static/themes/default/icons/ttrss.png :: [[https://tt-rss.org/gitlab/fox/tt-rss][GPL]]
- static/themes/default/icons/f-droid.png :: [[https://gitlab.com/fdroid/artwork/blob/master/fdroid-logo-2015/fdroid-logo.svg][CC-BY-SA 3.0 or GPLv3+]]
- static/themes/default/icons/google-play.png :: [[https://thenounproject.com/icon/887917/download/color/000000/png/][CC BY 3.0 US]]
- static/themes/default/icons/app-store.png :: [[https://thenounproject.com/icon/162372/download/color/000000/png/][CC BY 3.0 US]]
- static/themes/default/icons/apple.png :: [[https://thenounproject.com/icon/1203053/download/color/000000/png][CC BY 3.0 US]]
- static/themes/default/icons/windows.png :: [[https://thenounproject.com/icon/1206946/download/color/000000/png][CC BY 3.0 US]]
- static/themes/default/icons/gnu-linux.png :: [[https://upload.wikimedia.org/wikipedia/commons/9/95/Tux-icon-mono.svg][Public Domain]]
- static/themes/default/icons/mediawiki.svg :: [[http://tango.freedesktop.org/][Public Domain]]
- static/themes/default/icons/searx.png :: [[https://upload.wikimedia.org/wikipedia/commons/c/c4/Searx_logo.svg][CC BY 4.0]]
- static/themes/default/lato/Lato-*.woff2 :: [[http://www.latofonts.com/lato-free-fonts/|OFL-1.1]]
......@@ -39,17 +39,24 @@ the [FreedomBox Wiki](https://wiki.debian.org/FreedomBox/) and the
# Getting Started
See the INSTALL.md file for additional details and dependencies. To install run:
To have a running FreedomBox, first install Debian (Buster or higher) on a clean
machine. Then run:
$ sudo python3 setup.py install
$ sudo apt install freedombox
Run FreedomBox Service (Plinth) on the local system with:
Full instructions are available on FreedomBox
[QuickStart](https://wiki.debian.org/FreedomBox/Manual/QuickStart) page.
$ sudo plinth
For instructions on running the service on a local machine from source code, see
INSTALL.md. For instructions on setting up for development purposes, see
# Contributing
See the [HACKING](https://salsa.debian.org/freedombox-team/plinth/blob/master/HACKING.md) file for contributing to FreedomBox Service (Plinth).
See the [HACKING.md](https://salsa.debian.org/freedombox-team/plinth/blob/master/HACKING.md) file for contributing to FreedomBox Service (Plinth).
# Localization
......@@ -19,28 +19,52 @@
Vagrant.configure(2) do |config|
config.vm.box = "freedombox/plinth-dev"
config.vm.network "forwarded_port", guest: 443, host: 4430
config.vm.provision "shell", inline: <<-SHELL
cd /vagrant/
./setup.py install
apt update
DEBIAN_FRONTEND=noninteractive apt install -y $(plinth --list-dependencies)
systemctl daemon-reload
config.vm.synced_folder ".", "/vagrant", owner: "plinth", group: "plinth"
config.vm.provider "virtualbox" do |vb|
vb.cpus = 2
vb.memory = 2048
vb.linked_clone = true
config.vm.provision "shell", run: 'always', inline: <<-SHELL
# Disable automatic upgrades
/vagrant/actions/upgrades disable-auto
# Do not run system plinth
systemctl stop plinth
systemctl disable plinth
# Disable automatic upgrades
/vagrant/actions/upgrades disable-auto
config.vm.provision "shell", inline: <<-SHELL
cd /vagrant/
./setup.py install
systemctl daemon-reload
apt-get update
# In case new dependencies conflict with old dependencies
apt-mark hold freedombox
DEBIAN_FRONTEND=noninteractive apt-get install -y $(plinth --list-dependencies)
apt-mark unhold freedombox
# Install ncurses-term
DEBIAN_FRONTEND=noninteractive apt install -y ncurses-term
DEBIAN_FRONTEND=noninteractive apt-get install -y ncurses-term
config.vm.provision "tests", run: "never", type: "shell", path: "functional_tests/install.sh"
config.vm.post_up_message = "FreedomBox virtual machine is ready
for development. You can run the development version of Plinth using
the following command.
$ vagrant ssh
$ sudo /vagrant/run --develop
$ sudo -u plinth /vagrant/run --develop
Plinth will be available at https://localhost:4430/plinth (with
an invalid SSL certificate).
config.trigger.after [:up, :resume, :reload] do |trigger|
trigger.info = "Set plinth user permissions for development environment"
trigger.run_remote = {
path: "vagrant-scripts/plinth-user-permissions.py"
config.trigger.before :destroy do |trigger|
trigger.warn = "Performing cleanup steps"
trigger.run = {
path: "vagrant-scripts/post-box-destroy.py"
......@@ -36,6 +36,16 @@ def parse_arguments():
'--old-version', type=int, required=True,
help='Earlier version of the app that is already setup.')
subparser = subparsers.add_parser(
'enable', help='Enable a site/config/module in apache')
help='Name of the site/config/module to enable')
subparser.add_argument('--kind', choices=['site', 'config', 'module'])
subparser = subparsers.add_parser(
'disable', help='Disable a site/config/module in apache')
help='Name of the site/config/module to disable')
subparser.add_argument('--kind', choices=['site', 'config', 'module'])
subparsers.required = True
return parser.parse_args()
......@@ -63,8 +73,8 @@ def _sort_versions(versions):
return sorted(versions, key=_get_sort_key_of_version, reverse=True)
def _enable_latest_php(webserver):
"""Disable all older PHP versions and enable the latest one.
def _disable_mod_php(webserver):
"""Disable all mod_php versions.
Idempotent and harmless if all or no PHP modules are identified.
Problematic if only some modules are found.
......@@ -79,12 +89,9 @@ def _enable_latest_php(webserver):
versions = _sort_versions(versions)
for version in versions[1:]:
for version in versions:
webserver.disable('php' + version, kind='module')
if versions:
webserver.enable('php' + versions[0], kind='module')
def subcommand_setup(arguments):
"""Setup Apache configuration."""
......@@ -99,19 +106,27 @@ def subcommand_setup(arguments):
], check=True)
with action_utils.WebserverChange() as webserver:
# Disable mod_php as we have switched to mod_fcgi + php-fpm. Disable
# before switching away from mpm_prefork otherwise switching fails due
# dependency.
# set the prefork worker model
webserver.disable('mpm_event', kind='module')
webserver.disable('mpm_worker', kind='module')
webserver.enable('mpm_prefork', kind='module')
webserver.disable('mpm_prefork', kind='module')
webserver.enable('mpm_event', kind='module')
# enable miscellaneous modules.
webserver.enable('proxy', kind='module')
webserver.enable('proxy_http', kind='module')
webserver.enable('proxy_fcgi', kind='module')
webserver.enable('proxy_html', kind='module')
webserver.enable('rewrite', kind='module')
webserver.enable('macro', kind='module')
# enable GnuTLS
webserver.disable('ssl', kind='module')
webserver.enable('gnutls', kind='module')
# switch to mod_ssl from mod_gnutls
webserver.disable('gnutls', kind='module')
webserver.enable('ssl', kind='module')
# enable mod_alias for RedirectMatch
webserver.enable('alias', kind='module')
......@@ -119,17 +134,19 @@ def subcommand_setup(arguments):
# enable mod_headers for HSTS
webserver.enable('headers', kind='module')
# Various modules for authentication/authorization
webserver.enable('authnz_ldap', kind='module')
webserver.enable('auth_pubtkt', kind='module')
# enable some critical modules to avoid restart while installing
# FreedomBox applications.
webserver.enable('cgi', kind='module')
webserver.enable('authnz_ldap', kind='module')
webserver.disable('cgi', kind='module') # For process MPMs
webserver.enable('cgid', kind='module') # For threaded MPMs
webserver.enable('proxy_uwsgi', kind='module')
webserver.enable('proxy_wstunnel', kind='module')
# Workaround for bug https://bugs.debian.org/893481 . Ideally, don't
# explicitly enable module php and rely on the package
# libapache2-mod-php installing the current version of the package and
# enabling it. This ensures that when PHP version changes, the code is
# not broken.
# enable configuration for PHP-FPM
webserver.enable('php-fpm-freedombox', kind='config')
# enable users to share files uploaded to ~/public_html
webserver.enable('userdir', kind='module')
......@@ -142,12 +159,24 @@ def subcommand_setup(arguments):
# default sites
webserver.enable('000-default', kind='site')
webserver.disable('default-ssl', kind='site')
webserver.enable('default-tls', kind='site')
webserver.disable('default-tls', kind='site')
webserver.enable('default-ssl', kind='site')
webserver.enable('plinth', kind='site')
webserver.enable('plinth-ssl', kind='site')
# TODO: Check that the (name, kind) is a managed by FreedomBox before
# performing operation.
def subcommand_enable(arguments):
"""Enable an Apache site/config/module."""
action_utils.webserver_enable(arguments.name, arguments.kind)
def subcommand_disable(arguments):
"""Disable an Apache site/config/module."""
action_utils.webserver_disable(arguments.name, arguments.kind)
def main():
"""Parse arguments and perform all duties"""
arguments = parse_arguments()
......@@ -26,6 +26,7 @@ import datetime
import os
from OpenSSL import crypto
from plinth import action_utils
KEYS_DIRECTORY = '/etc/apache2/auth-pubtkt-keys'
......@@ -36,11 +37,9 @@ def parse_arguments():
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
help='create a key pair for the apache server '
'to sign auth_pubtkt tickets')
help='enabled the Apache module auth_pubtkt')
'create-key-pair', help='create a key pair for the apache server '
'to sign auth_pubtkt tickets')
gen_tkt = subparsers.add_parser('generate-ticket',
help='generate auth_pubtkt ticket')
gen_tkt.add_argument('--uid', help='username of the user')
......@@ -53,11 +52,6 @@ def parse_arguments():
return parser.parse_args()
def subcommand_enable_mod(_):
"""Safety check to make sure auth_pubtkt is enabled"""
action_utils.webserver_enable('auth_pubtkt', kind='module')
def subcommand_create_key_pair(_):
"""Create public/private key pair for signing the auth_pubtkt
......@@ -115,8 +109,8 @@ def subcommand_generate_ticket(arguments):
tokens = arguments.tokens
with open(private_key_file, 'r') as fil:
pkey = crypto.load_privatekey(crypto.FILETYPE_PEM, fil.read().encode())
valid_until = minutes_from_now(60)
grace_period = minutes_from_now(55)
valid_until = minutes_from_now(12 * 60)
grace_period = minutes_from_now(11 * 60)
print(create_ticket(pkey, uid, valid_until, tokens=tokens,
This diff is collapsed.
......@@ -64,7 +64,6 @@ def subcommand_setup(arguments):
with action_utils.WebserverChange() as webserver_change:
webserver_change.enable('proxy_wstunnel', kind='module')
......@@ -21,48 +21,66 @@ Configuration helper for FreedomBox general configuration.
import argparse
import os
import augeas
from plinth import action_utils
APACHE_CONFIGURATION = '/etc/apache2/conf-available/freedombox.conf'
from plinth.modules.config import (APACHE_HOMEPAGE_CONF_FILE_NAME,
def parse_arguments():
"""Return parsed command line arguments as dictionary."""
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
set_default_app = subparsers.add_parser(
help='Set the default app for this FreedomBox instance.')
set_default_app.add_argument('app', help='name of the default app')
set_home_page = subparsers.add_parser(
help='Set the home page for this FreedomBox instance.')
help='path to the webserver home page')
help='Reset the homepage of the Apache server.')
subparsers.required = True
return parser.parse_args()
def subcommand_set_default_app(arguments):
def subcommand_set_home_page(arguments):
"""Set the default app for this FreedomBox."""
app = arguments.app
conf_file_path = os.path.join('/etc/apache2/conf-available',
redirect_rule = 'RedirectMatch "^/$" "/{}"\n'.format(arguments.homepage)
with open(conf_file_path, 'w') as conf_file:
aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD +
def subcommand_reset_home_page(_):
"""Sets the Apache web server's home page to the default - /plinth."""
default_path = 'plinth'
aug = augeas.Augeas(
flags=augeas.Augeas.NO_LOAD + augeas.Augeas.NO_MODL_AUTOLOAD)
aug.set('/augeas/load/Httpd/lens', 'Httpd.lns')
aug.set('/augeas/load/Httpd/incl[last() + 1]', APACHE_CONFIGURATION)
aug.set('/augeas/load/Httpd/incl[last() + 1]', config_file)
aug.defvar('conf', '/files' + APACHE_CONFIGURATION)
aug.defvar('conf', '/files' + config_file)
for match in aug.match('/files' + APACHE_CONFIGURATION +
for match in aug.match('/files' + config_file +
if aug.get(match + "/arg[1]") == '''"^/$"''':
aug.set(match + "/arg[2]", '"/{}/"'.format(app))
aug.set(match + "/arg[2]", '"/{}"'.format(default_path))
def main():
"""Parse arguments and perform all duties."""
......@@ -154,6 +154,11 @@ def upgrade_config():
(not current_version or current_version > MOD_IRC_DEPRECATED_VERSION):
# BOSH port was changed from 5280 to 5443.
for listen_port in conf['listen']: