diff --git a/README.md b/README.md deleted file mode 100644 index 4e9d626f..00000000 --- a/README.md +++ /dev/null @@ -1,1513 +0,0 @@ -ansible-openwisp2 -================= - -[![Installing OpenWISP2](https://raw.githubusercontent.com/openwisp/ansible-openwisp2/master/docs/install-openwisp2.png)](https://www.youtube.com/watch?v=v_DUeFUGG8Q&index=1&list=PLPueLZei9c8_DEYgC5StOcR5bCAcQVfR8) - -[![Build Status](https://github.com/openwisp/ansible-openwisp2/workflows/Ansible%20OpenWISP2%20CI%20Build/badge.svg?branch=master)](https://github.com/openwisp/ansible-openwisp2/actions?query=workflow%3A%22Ansible+OpenWISP2+CI+Build%22) -[![Galaxy](http://img.shields.io/badge/galaxy-openwisp.openwisp2-blue.svg?style=flat-square)](https://galaxy.ansible.com/ui/standalone/roles/openwisp/openwisp2/) -[![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg?style=flat-square)](https://gitter.im/openwisp/general) - -Ansible role that installs the OpenWISP Server Application. - -Tested on **Debian (Bookworm/Bullseye)**, **Ubuntu (24/22/20 LTS)**. - -**NOTE**: it is highly suggested to use this procedure on clean virtual machines or linux containers. - -**Recommended minimum ansible core version**: 2.13. - -Demo -==== - -[Try the OpenWISP Demo](https://openwisp.org/demo.html) to get a quick -overview of what OpenWISP can do for you. - -Help OpenWISP -============= - -Like OpenWISP? Find out how to help us! - -- [Help us to grow our community](http://openwisp.io/docs/general/help-us.html) -- [How to contribute to OpenWISP](http://openwisp.io/docs/developer/contributing.html) - -Architecture -============ - -For more information, see [OpenWISP Architecture](https://openwisp.io/docs/general/architecture.html). - -[![openwisp2 modules diagram](https://raw.githubusercontent.com/openwisp/ansible-openwisp2/master/docs/openwisp2-modules-diagram.png)](https://openwisp.io/docs/general/architecture.html) - -System Requirements -=================== - -The following specifications will run a new, *empty* instance of OpenWISP. -Please ensure you account for the amount of disk space your use case will require, e.g. allocate -enough space for users to upload floor plan images. - -Hardware requirements (Recommended) ------------------------------------ - -- 2 CPUs -- 2 GB Memory -- Disk space - depends on the projected size of your database and uploaded photo images - -Keep in mind that increasing the number of celery workers will require -more memory and CPU. You will need to increase the amount of celery workers -as the number of devices you manage grows. - -For more information about how to increase concurrency, look for -the variables which end with `_concurrency` or `_autoscale` in the -[Role Variables](#role-variables) section. - -Software --------- - -Generally a fresh installation of one of the supported operating systems is sufficient; no pre-configuration required. The -Ansible Playbook will install and configure all dependencies and leave you with a running OpenWISP installation. - -Tips: Ensure the hostname of your target machine matches what is in your Ansible configuration file. Also, please ensure -that Ansible can access your target machine by SSH, be it either with a key or password. For more information see the -[Ansible Getting Started Documentation](https://docs.ansible.com/ansible/latest/user_guide/intro_getting_started.html). - -Supported Operating Systems ---------------------------- - -See the section "OS Platforms" on the -[ansible-galaxy page of ansible-openwisp2](https://galaxy.ansible.com/openwisp/openwisp2). - - -Usage (tutorial) -================ - -If you don't know how to use ansible, don't panic, this procedure will -guide you towards a fully working basic openwisp2 installation. - -If you already know how to use ansible, you can skip this tutorial. - -First of all you need to understand two key concepts: - -* for **"production server"** we mean a server (**not a laptop or a desktop computer!**) with public - ipv4 / ipv6 which is used to host openwisp2 -* for **"local machine"** we mean the host from which you launch ansible, eg: your own laptop - -Ansible is a configuration management tool that works by entering production servers via SSH, -**so you need to install it and configure it on the machine where you launch the deployment** and -this machine must be able to SSH into the production server. - -Ansible will be run on your local machine and from there it will connect to the production server -to install openwisp2. - -**If you are trying to install OpenWISP2 on your laptop or desktop pc just for testing purposes**, -please read [Install OpenWISP2 for testing in a VirtualBox VM](#install-openwisp2-for-testing-in-a-virtualbox-vm). - -Install ansible ---------------- - -Install ansible (minimum recommended version 2.13) **on your local machine** -(not the production server!) if you haven't done already. - -To **install ansible** we suggest you follow the official [ansible installation guide](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#installing-ansible-in-a-virtual-environment-with-pip). It is recommended to install ansible through a virtual environment to avoid dependency issues. - -Please ensure that you have the correct version of Jinja installed in your Python environment: -``` -pip install Jinja2>=2.11 -``` - -After having installed ansible, **you need to install git** (example for linux debian/ubuntu systems): - - sudo apt-get install git - -Install this role ------------------ - -For the sake of simplicity, the easiest thing is to install this role **on your local machine** -via `ansible-galaxy` (which was installed when installing ansible), therefore run: - - ansible-galaxy install openwisp.openwisp2 - -Ensure that you have the [`community.general`](https://github.com/ansible-collections/community.general) -and `ansible.posix` collections installed and up to date: - - ansible-galaxy collection install "community.general:>=3.6.0" - ansible-galaxy collection install "ansible.posix" - -Choose a working directory --------------------------- - -Choose a working directory **on your local machine** where to put the configuration of openwisp2. - -This will be useful when you will need to upgrade openwisp2. - -Eg: - - mkdir ~/openwisp2-ansible-playbook - cd ~/openwisp2-ansible-playbook - -Putting this working directory under version control is also a very good idea. - -Create inventory file ---------------------- - -The inventory file is where group of servers are defined. In our simple case we can -get away with defining just one group in which we will put just one server. - -Create a new file called `hosts` **in your local machine**'s working directory -(the directory just created in the previous step), with the following contents: - - [openwisp2] - openwisp2.mydomain.com - -Substitute `openwisp2.mydomain.com` with your **production server**'s hostname - **DO NOT REPLACE -`openwisp2.mydomain.com` WITH AN IP ADDRESS**, otherwise email sending through postfix will break, -causing 500 internal server errors on some operations. - -Create playbook file --------------------- - -Create a new playbook file `playbook.yml` **on your local machine** with the following contents: - -```yaml -- hosts: openwisp2 - become: "{{ become | default('yes') }}" - roles: - - openwisp.openwisp2 - vars: - openwisp2_default_from_email: "openwisp2@openwisp2.mydomain.com" -``` - -The line `become: "{{ become | default('yes') }}"` means ansible will use the `sudo` -program to run each command. You may remove this line if you don't need it (eg: if you are - `root` user on the production server). - -You may replace `openwisp2` on the `hosts` field with your production server's hostname if you desire. - -Substitute `openwisp2@openwisp2.mydomain.com` with what you deem most appropriate -as default sender for emails sent by OpenWISP 2. - -Run the playbook ----------------- - -Now is time to **deploy openwisp2 to the production server**. - -Run the playbook **from your local machine** with: - - ansible-playbook -i hosts playbook.yml -u -k --become -K - -Substitute `` with your **production server**'s username. - -The `-k` argument will need the `sshpass` program. - -You can remove `-k`, `--become` and `-K` if your public SSH key is installed on the server. - -**Tips**: - -- If you have an error like `Authentication or permission failure` then try to use *root* user `ansible-playbook -i hosts playbook.yml -u root -k` -- If you have an error about adding the host's fingerprint to the `known_hosts` file, you can simply connect to the host via SSH and answer yes when prompted; then you can run `ansible-playbook` again. - -When the playbook is done running, if you got no errors you can login at: - - https://openwisp2.mydomain.com/admin - username: admin - password: admin - -Substitute `openwisp2.mydomain.com` with your production server's hostname. - -Now proceed with the following steps: - -1. change the password (and the username if you like) of the superuser as soon as possible -2. update the `name` field of the default `Site` object to accurately display site name in email notifications -3. edit the information of the default organization -4. in the default organization you just updated, note down the automatically generated *shared secret* - option, you will need it to use the [auto-registration feature of openwisp-config](https://github.com/openwisp/openwisp-config#automatic-registration) -5. this Ansible role creates a default template to update ``authorized_keys`` on networking devices - using the default access credentials. The role will either use an existing SSH key pair or create - a new one if no SSH key pair exists on the host machine. - -Now you are ready to start configuring your network! **If you need help** you can ask questions -on one of the official [OpenWISP Support Channels](http://openwisp.org/support.html). - -Install ansible-openwisp2 for development ------------------------------------------ -If you need to modify the logic of this ansible role and you need to test your changes here we explain how to do it. - -First of all, create the directory where you want to place the repositories of the ansible roles and create directory roles. - -```bash - mkdir -p ~/openwisp-dev/roles - cd ~/openwisp-dev/roles -``` - -Clone `ansible-openwisp2` and `Stouts.postfix` as follows: - -```bash - git clone https://github.com/openwisp/ansible-openwisp2.git openwisp.openwisp2 - git clone https://github.com/Stouts/Stouts.postfix - git clone https://github.com/openwisp/ansible-ow-influxdb openwisp.influxdb -``` - -Now, go to the parent directory & create hosts file and playbook.yml: - -```bash - cd ../ - touch hosts - touch playbook.yml -``` - -From here on you can follow the instructions available at the following sections: - -- [Create inventory file](#create-inventory-file) -- [Create playbook file](#create-playbook-file) -- [Run the playbook](#run-the-playbook) - - -**Note:** Please remember to [install ansible](#install-ansible). - -All done! - -How to run tests ----------------- - -If you want to contribute to `ansible-openwisp2` you should run tests -in your development environment to ensure your changes are not breaking anything. - -To do that, proceed with the following steps: - -**Step 1**: Clone `ansible-openwisp2` - -Clone repository by: - - git clone https://github.com//ansible-openwisp2.git openwisp.openwisp2 - cd openwisp.openwisp2 - -**Step 2**: Install docker - -If you haven't installed docker yet, you need to install it (example for linux debian/ubuntu systems): - - sudo apt-get install docker.io - -**Step 3**: Install molecule and dependences - - pip install molecule[docker] molecule-plugins yamllint ansible-lint docker - -**Step 4**: Download docker images - - docker pull geerlingguy/docker-ubuntu2404-ansible:latest - docker pull geerlingguy/docker-ubuntu2204-ansible:latest - docker pull geerlingguy/docker-ubuntu2004-ansible:latest - docker pull geerlingguy/docker-debian12-ansible:latest - docker pull geerlingguy/docker-debian11-ansible:latest - -**Step 5**: Run molecule test - - molecule test -s local - -If you don't get any error message it means that the tests ran successfully without errors. - -**ProTip:** Use `molecule test --destroy=never` to speed up subsequent test runs. - -Install OpenWISP2 for testing in a VirtualBox VM -------------------------------------------------- - -If you want to try out **OpenWISP 2** in your own development environment, the safest -way is to use a VirtualBox Virtual Machine (from here on VM). - -### Using Vagrant - -**Since August 2018 there's a new fast and easy way to install OpenWISP 2 for testing -purposes** leveraging [Vagrant](https://www.vagrantup.com), a popular open source -tool for building and maintaining portable virtual software development environments. - -To use this new way, clone the repository [vagrant-openwisp2](https://github.com/openwisp/vagrant-openwisp2), -it contains the instructions (in the `README.md`) and the vagrant configuration -to perform the automatic installation. - -Alternatively, you can read on to learn how to install *VirtualBox* and run -*ansible-openwisp2* manually, this is useful if you need to test advanced -customisations of *OpenWISP*. - -### Installing Debian 9 on VirtualBox - -Install [VirtualBox](https://virtualbox.org) and create a new Virtual Machine running -Debian 11. A step-by-step guide is available -[here](http://www.brianlinkletter.com/installing-debian-linux-in-a-virtualbox-virtual-machine/), -however we need to change a few things to get ansible working. - -#### VM configuration - -Proceed with the installation as shown in the guide linked above, and come back -here when you see this screen: - -![Screenshot of the Software Selection screen](https://raw.githubusercontent.com/openwisp/ansible-openwisp2/master/docs/debian-software-selection.png) - -We're only running this as a server, so you can uncheck `Debian desktop environment`. -Make sure `SSH server` and `standard system utilities` are checked. - -Next, add a [Host-only Network Adapter](https://www.virtualbox.org/manual/ch06.html#network_hostonly) -and assign an IP address to the VM. - -- On the Main VirtualBox page, Go to `File > Host Network Manager` -- Click the + icon to create a new adapter -- Set the IPv4 address to `192.168.56.1` and the IPv4 Network Mask to `255.255.255.0`. You may need to select `Configure Adapter Manually` to do this. The IPv6 settings can be ignored - ![Screenshot of the Host-only network configuration screen](https://raw.githubusercontent.com/openwisp/ansible-openwisp2/master/docs/host-only-network.png) -- Shut off your VM -- In your VM settings, in the Network section, click Adapter 2 and Enable this Adapter -- Select Host-only adapter and the name of the adapter you created -- Boot up your VM, run `su`, and type in your superuser password -- Run `ls /sys/class/net` and take note of the output -- Run `nano /etc/network/interfaces` and add the following at the end of the file: - - auto enp0s8 - iface enp0s8 inet static - address 192.168.56.2 - netmask 255.255.255.0 - network 192.168.56.0 - broadcast 192.168.56.255 - - Replace `enp0s8` with the network interface not present in the file but is shown when running `ls /sys/class/net` -- Save the file with CtrlO then Enter, and exit with CtrlX -- Restart the machine by running `reboot` - -Make sure you can access your VM via ssh: - -```bash -ssh 192.168.56.2 -``` - -#### Back to your local machine - -Proceed with these steps in your **local machine**, not the VM. - -**Step 1**: [Install ansible](#install-ansible) - -**Step 2**: [Install the OpenWISP2 role for Ansible](#install-this-role) - -**Step 3**: [Set up a working directory](#choose-a-working-directory) - -**Step 4**: Create the `hosts` file - -Create an ansible inventory file named `hosts` **in your working directory** -(i.e. not in the VM) with the following contents: - -``` -[openwisp2] -192.168.56.2 -``` - -**Step 5**: Create the ansible playbook - -In the same directory where you created the `host` file, -create an empty file named `playbook.yml` which contains the following: - -```yaml -- hosts: openwisp2 - roles: - - openwisp.openwisp2 - # the following line is needed only when an IP address is used as the inventory hostname - vars: - postfix_myhostname: localhost -``` - -**Step 6**: Run the playbook - -```bash -ansible-playbook -i hosts playbook.yml -b -k -K --become-method=su -``` - -When the playbook ran successfully, you can log in at: - -``` -https://192.168.56.2/admin -username: admin -password: admin -``` - -Enabling the Monitoring module ------------------------------- - -The [Monitoring module](https://openwisp.io/docs/user/monitoring.html) -is enabled by default, it can be disabled by setting -``openwisp2_monitoring`` to ``false``. - -Enabling the Network Topology module ------------------------------------- - -To enable the [Network Topology module](https://openwisp.io/docs/user/network-topology.html) -you need to set `openwisp2_network_topology` to `true` in -your `playbook.yml` file. Here's a short summary of how to do this: - -**Step 1**: [Install ansible](#install-ansible) - -**Step 2**: [Install this role](#install-this-role) - -**Step 3**: [Create inventory file](#create-inventory-file) - -**Step 4**: Create a playbook file with following contents: - -```yaml -- hosts: openwisp2 - become: "{{ become | default('yes') }}" - roles: - - openwisp.openwisp2 - vars: - openwisp2_network_topology: true -``` - -**Step 5**: [Run the playbook](#run-the-playbook) - -When the playbook is done running, if you got no errors you can login at: - - https://openwisp2.mydomain.com/admin - username: admin - password: admin - -Enabling the Firmware Upgrader module -------------------------------------- - -**Note**: It is encouraged that you read the -[quick-start guide of openwisp-firmware-upgrader](https://openwisp.io/docs/user/firmware-upgrades.html#quickstart-guide) -before going ahead. - -To enable the [Firmware Upgrader](https://openwisp.io/docs/user/firmware-upgrades.html) -module you need to set `openwisp2_firmware_upgrader` to `true` in -your `playbook.yml` file. Here's a short summary of how to do this: - -**Step 1**: [Install ansible](#install-ansible) - -**Step 2**: [Install this role](#install-this-role) - -**Step 3**: [Create inventory file](#create-inventory-file) - -**Step 4**: Create a playbook file with following contents: - -```yaml -- hosts: openwisp2 - become: "{{ become | default('yes') }}" - roles: - - openwisp.openwisp2 - vars: - openwisp2_firmware_upgrader: true -``` - -**Step 5**: [Run the playbook](#run-the-playbook) - -When the playbook is done running, if you got no errors you can login at: - - https://openwisp2.mydomain.com/admin - username: admin - password: admin - -**Note**: You can configure [openwisp-firmware-upgrader specific settings](https://github.com/openwisp/openwisp-firmware-upgrader#settings) -using the `openwisp2_extra_django_settings` or -`openwisp2_extra_django_settings_instructions`. - -E.g: - -```yaml -- hosts: openwisp2 - become: "{{ become | default('yes') }}" - roles: - - openwisp.openwisp2 - vars: - openwisp2_firmware_upgrader: true - openwisp2_extra_django_settings_instructions: - - | - OPENWISP_CUSTOM_OPENWRT_IMAGES = ( - ('my-custom-image-squashfs-sysupgrade.bin', { - 'label': 'My Custom Image', - 'boards': ('MyCustomImage',) - }), - ) -``` - -Enabling the RADIUS module --------------------------- - -To enable the [RADIUS module](https://openwisp.io/docs/user/radius.html) -you need to set `openwisp2_radius` to `true` in -your `playbook.yml` file. Here's a short summary of how to do this: - -**Step 1**: [Install ansible](#install-ansible) - -**Step 2**: [Install this role](#install-this-role) - -**Step 3**: [Create inventory file](#create-inventory-file) - -**Step 4**: Create a playbook file with following contents: - -```yaml -- hosts: openwisp2 - become: "{{ become | default('yes') }}" - roles: - - openwisp.openwisp2 - vars: - openwisp2_radius: true - openwisp2_freeradius_install: true - # set to false when you don't want to register openwisp-radius - # API endpoints. - openwisp2_radius_urls: true -``` - -**Note:** `openwisp2_freeradius_install` option provides a basic -configuration of freeradius for openwisp, it sets up the -[radius user token mechanism](https://openwisp-radius.readthedocs.io/en/latest/user/api.html#radius-user-token-recommended) -if you want to use another mechanism or manage your freeradius separately, -please disable this option by setting it to `false`. - -**Step 5**: [Run the playbook](#run-the-playbook) - -When the playbook is done running, if you got no errors you can login at: - - https://openwisp2.mydomain.com/admin - username: admin - password: admin - -**Note:** for more information regarding radius configuration options, -look for the word "radius" in the -[Role variables](#role-variables) section of this document. - -### Configuring FreeRADIUS for WPA Enterprise (EAP-TTLS-PAP) - -You can use OpenWISP RADIUS for setting up WPA Enterprise (EAP-TTLS-PAP) -authentication. This allows to authenticate on WiFi networks using Django -user credentials. Prior to proceeding, ensure you've reviewed the tutorial -on [Setting Up WPA Enterprise (EAP-TTLS-PAP) authentication](https://openwisp.io/docs/tutorials/wpa-enterprise.html). -This documentation section complements the tutorial and focuses solely on -demonstrating the ansible role's capabilities to configure FreeRADIUS. - -**Note**: The ansible role supports OpenWISP's multi-tenancy by creating -individual FreeRADIUS sites for each organization. You must include -configuration details for **each organization** that will use WPA -Enterprise. - -Here's an example playbook which enables OpenWISP RADIUS module, -installs FreeRADIUS, and configures it for WPA Enterprise (EAP-TTLS-PAP): - - ```yaml - - hosts: openwisp2 - become: "{{ become | default('yes') }}" - roles: - - openwisp.openwisp2 - vars: - openwisp2_radius: true - openwisp2_freeradius_install: true - # Define a list of dictionaries detailing each organization's - # name, UUID, RADIUS token, and ports for authentication, - # accounting, and the inner tunnel. These details will be used - # to create FreeRADIUS sites tailored for WPA Enterprise - # (EAP-TTLS-PAP) authentication per organization. - freeradius_eap_orgs: - # A reference name for the organization, - # used in FreeRADIUS configurations. - # Don't use spaces or special characters. - - name: openwisp - # UUID of the organization. - # You can retrieve this from the organization admin - # in the OpenWISP web interface. - uuid: 00000000-0000-0000-0000-000000000000 - # Radius token of the organization. - # You can retrieve this from the organization admin - # in the OpenWISP web interface. - radius_token: secret-radius-token - # Port used by the authentication service for - # this FreeRADIUS site - auth_port: 1822 - # Port used by the accounting service for this FreeRADIUS site - acct_port: 1823 - # Port used by the authentication service of inner tunnel - # for this FreeRADIUS site - inner_tunnel_auth_port: 18230 - # If you want to use a custom certificate for FreeRADIUS - # EAP module, you can specify the path to the CA, server - # certificate, and private key, and DH key as follows. - # Ensure that these files can be read by the "freerad" user. - cert: /etc/freeradius/certs/cert.pem - private_key: /etc/freeradius/certs/key.pem - ca: /etc/freeradius/certs/ca.crt - dh: /etc/freeradius/certs/dh - tls_config_extra: | - private_key_password = whatever - ecdh_curve = "prime256v1" - - # You can add as many organizations as you want - - name: demo - uuid: 00000000-0000-0000-0000-000000000001 - radius_secret: demo-radius-token - auth_port: 1832 - acct_port: 1833 - inner_tunnel_auth_port: 18330 - # If you omit the certificate fields, - # the FreeRADIUS site will use the default certificates - # located in /etc/freeradius/certs. -``` - -**Note**: In the example above, custom ports 1822, 1823, and 18230 -are utilized for FreeRADIUS authentication, accounting, and inner tunnel -authentication, respectively. These custom ports are specified because the -Ansible role creates a common FreeRADIUS site for all organizations, which -also supports captive portal functionality. This common site is configured -to listen on the default FreeRADIUS ports 1812, 1813, and 18120. Therefore, -when configuring WPA Enterprise authentication for each organization, -unique ports must be provided to ensure proper isolation and functionality. - -#### Using Let's Encrypt Certificate for WPA Enterprise (EAP-TTLS-PAP) - -In this section, we demonstrate how to utilize Let's Encrypt certificates -for WPA Enterprise (EAP-TTLS-PAP) authentication. Similar to the -[Automatic SSL certificate](#automatic-ssl-certificate), we use -[geerlingguy.certbot](https://galaxy.ansible.com/geerlingguy/certbot/) -role to automatically install and renew a valid SSL certificate. - -The following example playbook achieves the following goals: - -- Provision a separate Let's Encrypt certificate for the - `freeradius.yourdomain.com` hostname. This certificate will be - utilized by the FreeRADIUS site for WPA Enterprise authentication. -- Create a renewal hook to set permissions on the generated certificate - so the FreeRADIUS server can read it. - -**Note**: You can also use the same SSL certificate for both Nginx and -FreeRADIUS, but it's crucial to understand the security implications. -Please exercise caution and refer to the example playbook comments for -guidance. - -```yaml - - hosts: openwisp2 - become: "{{ become | default('yes') }}" - roles: - - geerlingguy.certbot - - openwisp.openwisp2 - vars: - # certbot configuration - certbot_auto_renew_minute: "20" - certbot_auto_renew_hour: "5" - certbot_create_if_missing: true - certbot_auto_renew_user: "" - certbot_certs: - - email: "" - domains: - - "{{ inventory_hostname }}" - # If you choose to re-use the same certificate for both services, - # you can omit the following item in your playbook. - - email: "" - domains: - - "freeradius.yourdomain.com" - # Configuration to use Let's Encrypt certificate for OpenWISP server (Nnginx) - openwisp2_ssl_cert: "/etc/letsencrypt/live/{{ inventory_hostname }}/fullchain.pem" - openwisp2_ssl_key: "/etc/letsencrypt/live/{{ inventory_hostname }}/privkey.pem" - # Configuration for openwisp-radius - openwisp2_radius: true - openwisp2_freeradius_install: true - freeradius_eap_orgs: - - name: demo - uuid: 00000000-0000-0000-0000-000000000001 - radius_secret: demo-radius-token - auth_port: 1832 - acct_port: 1833 - inner_tunnel_auth_port: 18330 - # Update the cert_file and private_key paths to point to the - # Let's Encrypt certificate. - cert: /etc/letsencrypt/live/freeradius.yourdomain.com/fullchain.pem - private_key: /etc/letsencrypt/live/freeradius.yourdomain.com/privkey.pem - # If you choose to re-use the same certificate for both services, - # your configuration would look like this - # cert: /etc/letsencrypt/live/{{ inventory_hostname }}/fullchain.pem - # private_key: /etc/letsencrypt/live/{{ inventory_hostname }}/privkey.pem - tasks: - # Tasks to ensure the Let's Encrypt certificate can be read by the FreeRADIUS server. - # If you are using the same certificate for both services, you need to - # replace "freeradius.yourdomain.com" with "{{ inventory_hostname }}" - # in the following task. - - name: "Create a renewal hook for setting permissions on /etc/letsencrypt/live/freeradius.yourdomain.com" - copy: - content: | - #!/bin/bash - chown -R root:freerad /etc/letsencrypt/live/ /etc/letsencrypt/archive/ - chmod 0750 /etc/letsencrypt/live/ /etc/letsencrypt/archive/ - chmod -R 0640 /etc/letsencrypt/archive/freeradius.yourdomain.com/ - chmod 0750 /etc/letsencrypt/archive/freeradius.yourdomain.com/ - dest: /etc/letsencrypt/renewal-hooks/post/chown_freerad - owner: root - group: root - mode: '0700' - register: chown_freerad_result - - name: Change the ownership of the certificate files - when: chown_freerad_result.changed - command: /etc/letsencrypt/renewal-hooks/post/chown_freerad -``` - -Configuring CORS Headers ------------------------- - -While integrating OpenWISP with external services, you can -run into issues related to [CORS (Cross-Origin Resource Sharing)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). This role -allows users to configure the CORS headers with the help of -[django-cors-headers](https://github.com/adamchainz/django-cors-headers) -package. Here's a short summary of how to do this: - -**Step 1**: [Install ansible](#install-ansible) - -**Step 2**: [Install this role](#install-this-role) - -**Step 3**: [Create inventory file](#create-inventory-file) - -**Step 4**: Create a playbook file with following contents: - -```yaml -- hosts: openwisp2 - become: "{{ become | default('yes') }}" - roles: - - openwisp.openwisp2 - vars: - # Cross-Origin Resource Sharing (CORS) settings - openwisp2_django_cors: - enabled: true - allowed_origins_list: - - https://frontend.openwisp.org - - https://logs.openwisp.org -``` - -**Note:** to learn about the supported fields of the `openwisp2_django_cors` variable, -look for the word "openwisp2_django_cors" in the -[Role variables](#role-variables) section of this document. - -**Step 5**: [Run the playbook](#run-the-playbook) - -When the playbook is done running, if you got no errors you can login at: - -``` -https://openwisp2.mydomain.com/admin -username: admin -password: admin -``` - -The ansible-openwisp2 only provides abstraction (variables) -for handful of settings available in [django-cors-headers](https://github.com/adamchainz/django-cors-headers) -module. Use the `openwisp2_extra_django_settings_instructions` or -`openwisp2_extra_django_settings` variable to configure additional -setting of `django-cors-headers` as shown in the following example: - -```yaml -- hosts: openwisp2 - become: "{{ become | default('yes') }}" - roles: - - openwisp.openwisp2 - vars: - openwisp2_django_cors: - enabled: true - allowed_origins_list: - - https://frontend.openwisp.org - - https://logs.openwisp.org - replace_https_referer: true - # Configuring additional settings for django-cors-headers - openwisp2_extra_django_settings_instructions: - - | - CORS_ALLOW_CREDENTIALS = True - CORS_ALLOW_ALL_ORIGINS = True -``` - -Deploying custom static content -=============================== - -For deploying custom static content (HTML files, etc.) add all -the static content in `files/ow2_static` directory. The files inside -`files/ow2_static` will be uploaded to a directory named `static_custom` -in `openwisp2_path`. - -This is helpful for [customizing OpenWISP's theme](https://github.com/openwisp/openwisp-utils#openwisp_admin_theme_links). - -E.g., if you added a custom CSS file in `files/ow2_static/css/custom.css`, the -file location to use in [OPENWISP_ADMIN_THEME_LINKS](https://github.com/openwisp/openwisp-utils#openwisp_admin_theme_links) setting will be `css/custom.css`. - -Deploying the upcoming release of OpenWISP -========================================== - -The following steps will help you set up and install the new version of OpenWISP -which is not released yet, but ships new features and fixes. - -Create a directory for organizing your playbook, roles and collections. In this example, -`openwisp-dev` is used. Create `roles` and `collections` directories in `~/openwisp-dev`. - -``` -mkdir -p ~/openwisp-dev/roles -mkdir -p ~/openwisp-dev/collections -``` - -Change directory to `~/openwisp-dev/` in terminal and create configuration -and requirement files for Ansible. - -``` -cd ~/openwisp-dev/ -touch ansible.cfg -touch requirements.yml -``` - -Setup `roles_path` and `collections_paths` variables in `ansible.cfg` as follows: - -``` -[defaults] -roles_path=~/openwisp-dev/roles -collections_paths=~/openwisp-dev/collections -``` - -Ensure your `requirements.yml` contains following content: - -```yml ---- -roles: - - src: https://github.com/openwisp/ansible-openwisp2.git - version: master - name: openwisp.openwisp2-dev -collections: - - name: community.general - version: ">=3.6.0" -``` - -Install requirements from the `requirements.yml` as follows - -``` -ansible-galaxy install -r requirements.yml -``` - -Now, create hosts file and playbook.yml: - -``` -touch hosts -touch playbook.yml -``` - -Follow instructions in ["Create inventory file"](#create-inventory-file) section to -configure `hosts` file. - -You can reference the example playbook below (tested on Debian 11) -for installing a fully-featured version of OpenWISP. - -```yml -- hosts: openwisp2 - become: "{{ become | default('yes') }}" - roles: - - openwisp.openwisp2-dev - vars: - openwisp2_network_topology: true - openwisp2_firmware_upgrader: true - openwisp2_radius: true - openwisp2_monitoring: true # monitoring is enabled by default -``` - -Read ["Role Variables"](#role-variables) section to learn about -available configuration variables. - -Follow instructions in ["Run the playbook"](#run-the-playbook) section to -run above playbook. - -Troubleshooting -=============== - -OpenWISP 2 is deployed using **uWSGI**, it also uses **daphne** fo - WebSockets and **celery** as task queue. - - All this services are run by **supervisor**. - -``` -sudo service supervisor start|stop|status -``` - -You can view each individual process run by supervisor with the next command. - -More info at [Running supervisorctl](http://supervisord.org/running.html#running-supervisorctl) - -``` -sudo supervisorctl status -``` - -**nginx** is in front of **uWSGI**. You can control it with next command - -``` -service nginx status start|stop|status -``` - -OpenWISP 2 is installed in `/opt/openwisp2` -(unless you changed the ``openwisp2_path`` variable in the -ansible playbook configuration), these are some useful directories to -look for when experiencing issues. - -| Location | Description | -|---------------------------|-------------------------------| -| /opt/openwisp2 | The OpenWISP 2 root dir. | -| /opt/openwisp2/log | Log files | -| /opt/openwisp2/env | Python virtual env | -| /opt/openwisp2/db.sqlite3 | OpenWISP 2 sqlite database | - -All processes are running as ``www-data`` user. - -If you need to copy or edit files, you can switch to ``www-data`` -user with the commands - -``` -sudo su www-data -s /bin/bash -cd /opt/openwisp2 -source env/bin/activate -``` - -SSL certificate gotchas -======================= - -When you access the admin website you will get an SSL certificate warning because the -playbook creates a self-signed (untrusted) SSL certificate. You can get rid of the warning by -installing your own trusted certificate and set the `openwisp2_ssl_cert` and `openwisp2_ssl_key` -variables accordingly or by following the instructions explained in the section -["Automatic SSL certificate"](#automatic-ssl-certificate). - -If you keep the untrusted certificate, you will also need to disable SSL verification on devices -using [openwisp-config](https://github.com/openwisp/openwisp-config) by setting `verify_ssl` to `0`, -although I advice against using this kind of setup in a production environment. - -Automatic SSL certificate -========================= - -This section explains how to **automatically install and renew a valid SSL certificate** signed by -[letsencrypt](https://letsencrypt.org/). - -The first thing you have to do is to setup a valid domain for your openwisp2 instance, this means -your inventory file (hosts) should look like the following: - -``` -[openwisp2] -openwisp2.yourdomain.com -``` - -You must be able to add a DNS record for `openwisp2.yourdomain.com`, you cannot use an ip address -in place of `openwisp2.yourdomain.com`. - -Once your domain is set up and the DNS record is propagated, proceed by installing the ansible role -[geerlingguy.certbot](https://galaxy.ansible.com/geerlingguy/certbot/): - -``` -ansible-galaxy install geerlingguy.certbot -``` - -Then proceed to edit your `playbook.yml` so that it will look similar to the following example: - -```yaml -- hosts: openwisp2 - become: "{{ become | default('yes') }}" - roles: - - geerlingguy.certbot - - openwisp.openwisp2 - vars: - # SSL certificates - openwisp2_ssl_cert: "/etc/letsencrypt/live/{{ inventory_hostname }}/fullchain.pem" - openwisp2_ssl_key: "/etc/letsencrypt/live/{{ inventory_hostname }}/privkey.pem" - - # certbot configuration - certbot_auto_renew_minute: "20" - certbot_auto_renew_hour: "5" - certbot_create_if_missing: true - certbot_auto_renew_user: "" - certbot_certs: - - email: "" - domains: - - "{{ inventory_hostname }}" - pre_tasks: - - name: Update APT package cache - apt: - update_cache: true - changed_when: false - retries: 5 - delay: 10 - register: result - until: result is success -``` - -Read the [documentation of geerlingguy.certbot](https://github.com/geerlingguy/ansible-role-certbot#readme) -to learn more about configuration of certbot role. - -Once you have set up all the variables correctly, run the playbook again. - -Upgrading openwisp2 -=================== - -**It's highly recommended to back up your current instance -before upgrading**. - -Update this ansible-role via `ansible-galaxy`: - - ansible-galaxy install --force openwisp.openwisp2 - -Run `ansible-playbook` again **from your local machine**: - - ansible-playbook -i hosts playbook.yml - -You may also run the playbook automatically periodically or when a new release of OpenWISP2, for -example, by setting up a continuous integration system. - -Role variables -============== - -This role has many variables values that can be changed to best suit -your needs. - -Below are listed all the variables you can customize (you may also want to take a look at -[the default values of these variables](https://github.com/openwisp/ansible-openwisp2/blob/master/defaults/main.yml)). - -```yaml -- hosts: yourhost - roles: - # you can add other roles here - - openwisp.openwisp2 - vars: - # Enable the modules you want to use - openwisp2_network_topology: false - openwisp2_firmware_upgrader: false - openwisp2_monitoring: true - # you may replace the values of these variables with any value or URL - # supported by pip (the python package installer) - # use these to install forks, branches or development versions - # WARNING: only do this if you know what you are doing; disruption - # of service is very likely to occur if these variables are changed - # without careful analysis and testing - openwisp2_controller_version: "openwisp-controller~=1.0.0" - openwisp2_network_topology_version: "openwisp-network-topology~=1.0.0" - openwisp2_firmware_upgrader_version: "openwisp-firmware-upgrader~=1.0.0" - openwisp2_monitoring_version: "openwisp-monitoring~=1.0.0" - openwisp2_radius_version: "openwisp-radius~=1.0.0" - openwisp2_django_version: "django~=3.2.13" - # Setting this to true will enable subnet division feature of - # openwisp-controller. Refer openwisp-controller documentation - # for more information. https://github.com/openwisp/openwisp-controller#subnet-division-app - # By default, it is set to false. - openwisp2_controller_subnet_division: true - # when openwisp2_radius_urls is set to false, the radius module - # is setup but it's urls are not added, which means API and social - # views cannot be used, this is helpful if you have an external - # radius instance. - openwisp2_radius_urls: "{{ openwisp2_radius }}" - openwisp2_path: /opt/openwisp2 - # It is recommended that you change the value of this variable if you intend to use - # OpenWISP2 in production, as a misconfiguration may result in emails not being sent - openwisp2_default_from_email: "openwisp2@yourhostname.com" - # Email backend used by Django for sending emails. By default, the role - # uses "CeleryEmailBackend" from django-celery-email. - # (https://github.com/pmclanahan/django-celery-email) - openwisp2_email_backend: "djcelery_email.backends.CeleryEmailBackend" - # Email timeout in seconds used by Django for blocking operations - # like connection attempts. For more info read the Django documentation, - # https://docs.djangoproject.com/en/3.2/ref/settings/#email-timeout. - # Defaults to 10 seconds. - openwisp2_email_timeout: 5 - # edit database settings only if you are not using sqlite - # eg, for deploying with PostgreSQL (recommended for production usage) - # you will need the PostGIS spatial extension, find more info at: - # https://docs.djangoproject.com/en/4.1/ref/contrib/gis/tutorial/ - openwisp2_database: - engine: django.contrib.gis.db.backends.postgis - name: "{{ DB_NAME }}" - user: "{{ DB_USER }}" - host: "{{ DB_HOST }}" - password: "{{ DB_PASSWORD }}" - port: 5432 - # SPATIALITE_LIBRARY_PATH django setting - # The role will attempt determining the right mod-spatialite path automatically - # But you can use this variable to customize the path or fix future arising issues - openwisp2_spatialite_path: "mod_spatialite.so" - # customize other django settings: - openwisp2_language_code: en-gb - openwisp2_time_zone: UTC - # openwisp-controller context - openwisp2_context: {} - # additional allowed hosts - openwisp2_allowed_hosts: - - myadditionalhost.openwisp.org - # geographic map settings - openwisp2_leaflet_config: - DEFAULT_CENTER: [42.06775, 12.62011] - DEFAULT_ZOOM: 6 - # enable/disable geocoding check - openwisp2_geocoding_check: true - # specify path to a valid SSL certificate and key - # (a self-signed SSL cert will be generated if omitted) - openwisp2_ssl_cert: "/etc/nginx/ssl/server.crt" - openwisp2_ssl_key: "/etc/nginx/ssl/server.key" - # customize the self-signed SSL certificate info if needed - openwisp2_ssl_country: "US" - openwisp2_ssl_state: "California" - openwisp2_ssl_locality: "San Francisco" - openwisp2_ssl_organization: "IT dep." - # the following setting controls which ip address range - # is allowed to access the controller via unencrypted HTTP - # (this feature is disabled by default) - openwisp2_http_allowed_ip: "10.8.0.0/16" - # additional python packages that will be installed with pip - openwisp2_extra_python_packages: - - bpython - - django-owm-legacy - # additional django apps that will be added to settings.INSTALLED_APPS - # (if the app needs to be installed, the name its python package - # must be also added to the openwisp2_extra_python_packages var) - openwisp2_extra_django_apps: - - owm_legacy - # additional django settings example - openwisp2_extra_django_settings: - CSRF_COOKIE_AGE: 2620800.0 - # in case you need to add python instructions to the django settings file - openwisp2_extra_django_settings_instructions: - - TEMPLATES[0]['OPTIONS']['loaders'].insert(0, 'apptemplates.Loader') - # extra URL settings for django - openwisp2_extra_urls: - - "path(r'', include('my_custom_app.urls'))" - # allows to specify imports that are used in the websocket routes, eg: - openwisp2_websocket_extra_imports: - - from my_custom_app.websockets.routing import get_routes as get_custom_app_routes - # allows to specify extra websocket routes, eg: - openwisp2_websocket_extra_routes: - # Callable that returns a list of routes - - get_custom_app_routes() - # List of routes - - "[path('ws/custom-app/', consumer.CustomAppConsumer.as_asgi())]" - # controller URL are enabled by default - # but can be disabled in multi-VM installations if needed - openwisp2_controller_urls: true - # The default retention policy that applies to the timeseries data - # https://github.com/openwisp/openwisp-monitoring#openwisp-monitoring-default-retention-policy - openwisp2_monitoring_default_retention_policy: "26280h0m0s" # 3 years - # whether NGINX should be installed - openwisp2_nginx_install: true - # spdy protocol support (disabled by default) - openwisp2_nginx_spdy: false - # HTTP2 protocol support (disabled by default) - openwisp2_nginx_http2: false - # ipv6 must be enabled explicitly to avoid errors - openwisp2_nginx_ipv6: false - # nginx client_max_body_size setting - openwisp2_nginx_client_max_body_size: 10M - # list of upstream servers for OpenWISP - openwisp2_nginx_openwisp_server: - - "localhost:8000" - # dictionary containing more nginx settings for - # the 443 section of the openwisp2 nginx configuration - # IMPORTANT: 1. you can add more nginx settings in this dictionary - # 2. here we list the default values used - openwisp2_nginx_ssl_config: - gzip: "on" - gzip_comp_level: "6" - gzip_proxied: "any" - gzip_min_length: "1000" - gzip_types: - - "text/plain" - - "text/html" - - "image/svg+xml" - - "application/json" - - "application/javascript" - - "text/xml" - - "text/css" - - "application/xml" - - "application/x-font-ttf" - - "font/opentype" - # nginx error log configuration - openwisp2_nginx_access_log: "{{ openwisp2_path }}/log/nginx.access.log" - openwisp2_nginx_error_log: "{{ openwisp2_path }}/log/nginx.error.log error" - # nginx Content Security Policy header, customize if needed - openwisp2_nginx_csp: > - CUSTOM_NGINX_SECURITY_POLICY - # uwsgi gid, omitted by default - openwisp2_uwsgi_gid: null - # number of uWSGI process to spawn. Default value is 1. - openwisp2_uwsgi_processes: 1 - # number of threads each uWSGI process will have. Default value is 1. - openwisp2_uwsgi_threads: 2 - # value of the listen queue of uWSGI - openwisp2_uwsgi_listen: 100 - # socket on which uwsgi should listen. Defaults to UNIX socket - # at "{{ openwisp2_path }}/uwsgi.sock" - openwisp2_uwsgi_socket: 127.0.0.1:8000 - # extra uwsgi configuration parameters that cannot be - # configured using dedicated ansible variables - openwisp2_uwsgi_extra_conf: | - single-interpreter=True - log-4xx=True - log-5xx=True - disable-logging=True - auto-procname=True - # whether daphne should be installed - # must be enabled for serving websocket requests - openwisp2_daphne_install: true - # number of daphne process to spawn. Default value is 1 - openwisp2_daphne_processes: 2 - # maximum time to allow a websocket to be connected (in seconds) - openwisp2_daphne_websocket_timeout: 1800 - # the following setting controls which ip address range - # is allowed to access the openwisp2 admin web interface - # (by default any IP is allowed) - openwisp2_admin_allowed_network: null - # install ntp client (enabled by default) - openwisp2_install_ntp: true - # if you have any custom supervisor service, you can - # configure it to restart along with other supervisor services - openwisp2_extra_supervisor_restart: - - name: my_custom_service - when: my_custom_service_enabled - # Disable usage metric collection. It is enabled by default. - # Read more about it at - # https://openwisp.io/docs/user/usage-metric-collection.html - openwisp2_usage_metric_collection: false - # enable sentry example - openwisp2_sentry: - dsn: "https://7d2e3cd61acc32eca1fb2a390f7b55e1:bf82aab5ddn4422688e34a486c7426e3@getsentry.com:443/12345" - openwisp2_default_cert_validity: 1825 - openwisp2_default_ca_validity: 3650 - # the following options for redis allow to configure an external redis instance if needed - openwisp2_redis_install: true - openwisp2_redis_host: localhost - openwisp2_redis_port: 6379 - openwisp2_redis_cache_url: "redis://{{ openwisp2_redis_host }}:{{ openwisp2_redis_port }}/1" - # the following options are required to configure influxdb which is used in openwisp-monitoring - openwisp2_influxdb_install: true - openwisp2_timeseries_database: - backend: "openwisp_monitoring.db.backends.influxdb" - user: "openwisp" - password: "openwisp" - name: "openwisp2" - host: "localhost" - port: 8086 - # celery concurrency for the default queue, by default the number of CPUs is used - # celery concurrency for the default queue, by default it is set to 1 - # Setting it to "null" will make concurrency equal to number of CPUs if autoscaling is not used - openwisp2_celery_concurrency: null - # alternative to the previous option, the celery autoscale option can be set if needed - # for more info, consult the documentation of celery regarding "autoscaling" - # by default it is set to "null" (no autoscaling) - openwisp2_celery_autoscale: 4,1 - # prefetch multiplier for the default queue, - # the default value is calculated automatically by celery - openwisp2_celery_prefetch_multiplier: null - # celery queuing mode for the default queue, - # leaving the default will work for most cases - openwisp2_celery_optimization: default - # whether the dedicated celerybeat worker is enabled which is - # responsible for triggering periodic tasks - # must be turned on unless there's another server running celerybeat - openwisp2_celerybeat: true - # whether the dedicated worker for the celery "network" queue is enabled - # must be turned on unless there's another server running a worker for this queue - openwisp2_celery_network: true - # concurrency option for the "network" queue (a worker is dedicated solely to network operations) - # the default is 1. Setting it to "null" will make concurrency equal to number of CPUs if autoscaling is not used. - openwisp2_celery_network_concurrency: null - # alternative to the previous option, the celery autoscale option can be set if needed - # for more info, consult the documentation of celery regarding "autoscaling" - # by default it is set to "null" (no autoscaling) - openwisp2_celery_network_autoscale: 8,4 - # prefetch multiplier for the "network" queue, - # the default is 1, which mean no prefetching, - # because the network tasks are long running and is better - # to distribute the tasks to multiple processes - openwisp2_celery_network_prefetch_multiplier: 1 - # celery queuing mode for the "network" queue, - # fair mode is used in this case, which means - # tasks will be equally distributed among workers - openwisp2_celery_network_optimization: fair - # whether the dedicated worker for the celery "firmware_upgrader" queue is enabled - # must be turned on unless there's another server running a worker for this queue - openwisp2_celery_firmware_upgrader: true - # concurrency option for the "firmware_upgrader" queue (a worker is dedicated solely to firmware upgrade operations) - # the default is 1. Setting it to "null" will make concurrency equal to number of CPUs if autoscaling is not used - openwisp2_celery_firmware_upgrader_concurrency: null - # alternative to the previous option, the celery autoscale option can be set if needed - # for more info, consult the documentation of celery regarding "autoscaling" - # by default it is set to "null" (no autoscaling) - openwisp2_celery_firmware_upgrader_autoscale: 8,4 - # prefetch multiplier for the "firmware_upgrader" queue, - # the default is 1, which mean no prefetching, - # because the firmware upgrade tasks are long running and is better - # to distribute the tasks to multiple processes - openwisp2_celery_firmware_upgrader_prefetch_multiplier: 1 - # celery queuing mode for the "firmware_upgrader" queue, - # fair mode is used in this case, which means - # tasks will be equally distributed among workers - openwisp2_celery_firmware_upgrader_optimization: fair - # whether the dedicated worker for the celery "monitoring" queue is enabled - # must be turned on unless there's another server running a worker for this queue - openwisp2_celery_monitoring: true - # concurrency option for the "monitoring" queue (a worker is dedicated solely to monitoring operations) - # the default is 2. Setting it to "null" will make concurrency equal to number of CPUs - # if autoscaling is not used. - openwisp2_celery_monitoring_concurrency: null - # alternative to the previous option, the celery autoscale option can be set if needed - # for more info, consult the documentation of celery regarding "autoscaling" - # by default it is set to "null" (no autoscaling) - openwisp2_celery_monitoring_autoscale: 4,8 - # prefetch multiplier for the "monitoring" queue, - # the default is 1, which mean no prefetching, - # because the monitoring tasks can be long running and is better - # to distribute the tasks to multiple processes - openwisp2_celery_monitoring_prefetch_multiplier: 1 - # celery queuing mode for the "monitoring" queue, - # fair mode is used in this case, which means - # tasks will be equally distributed among workers - openwisp2_celery_monitoring_optimization: fair - # whether the default celery task routes should be written to the settings.py file - # turn this off if you're defining custom task routing rules - openwisp2_celery_task_routes_defaults: true - # celery settings - openwisp2_celery_broker_url: redis://{{ openwisp2_redis_host }}:{{ openwisp2_redis_port }}/3 - openwisp2_celery_task_acks_late: true - # maximum number of retries by celery before giving up when broker is unreachable - openwisp2_celery_broker_max_tries: 10 - # whether to activate the django logging configuration in celery - # if set to true, will log all the celery events in the same log stream used by django - # which will cause log lines to be written to "{{ openwisp2_path }}/log/openwisp2.log" - # instead of "{{ openwisp2_path }}/log/celery.log" and "{{ openwisp2_path }}/log/celerybeat.log" - openwisp2_django_celery_logging: false - # postfix is installed by default, set to false if you don't need it - openwisp2_postfix_install: true - # allow overriding default `postfix_smtp_sasl_auth_enable` variable - postfix_smtp_sasl_auth_enable_override: true - # allow overriding postfix_smtpd_relay_restrictions - postfix_smtpd_relay_restrictions_override: permit_mynetworks - # allows overriding the default duration for keeping notifications - openwisp2_notifications_delete_old_notifications: 10 - # Expiration time limit (in seconds) of magic sign-in links. - # Magic sign-in links are used only when OpenWISP RADIUS is enabled. - openwisp2_django_sesame_max_age: 1800 # 30 minutes - # Maximum file size(in bytes) allowed to be uploaded as firmware image. - # It overrides "openwisp2_nginx_client_max_body_size" setting - # and updates nginx configuration accordingly. - openwisp2_firmware_upgrader_max_file_size: 41943040 # 40MB - # to add multi-language support - openwisp2_internationalization: true - openwisp2_users_auth_api: true - # Allows setting OPENWISP_USERS_USER_PASSWORD_EXPIRATION setting. - # Read https://github.com/openwisp/openwisp-users#openwisp_users_user_password_expiration - openwisp2_users_user_password_expiration: 30 - # Allows setting OPENWISP_USERS_STAFF_USER_PASSWORD_EXPIRATION setting. - # Read https://github.com/openwisp/openwisp-users#openwisp_users_staff_user_password_expiration - openwisp2_users_staff_user_password_expiration: 30 - # used for SMS verification, the default is a dummy SMS backend - # which prints to standard output and hence does nothing - # one of the available providers from django-sendsms can be - # used or alternatively, you can write a backend class for your - # favorite SMS API gateway - openwisp2_radius_sms_backend: "sendsms.backends.console.SmsBackend" - openwisp2_radius_sms_token_max_ip_daily: 25 - openwisp2_radius_delete_old_radiusbatch_users: 365 - openwisp2_radius_cleanup_stale_radacct: 1 - openwisp2_radius_delete_old_postauth: 365 - # days for which the radius accounting sessions (radacct) are retained, - # 0 means sessions are kept forever. - # we highly suggest to set this number according - # to the privacy regulation of your jurisdiction - openwisp2_radius_delete_old_radacct: 365 - # days after which inactive users will flagged as unverified - # Read https://openwisp-radius.readthedocs.io/en/latest/user/settings.html#openwisp-radius-unverify-inactive-users - openwisp2_radius_unverify_inactive_users: 540 - # days after which inactive users will be deleted - # Read https://openwisp-radius.readthedocs.io/en/latest/user/settings.html#openwisp-radius-delete-inactive-users - openwisp2_radius_delete_inactive_users: 540 - openwisp2_radius_allowed_hosts: ["127.0.0.1"] - # allow disabling celery beat tasks if needed - openwisp2_monitoring_periodic_tasks: true - openwisp2_radius_periodic_tasks: true - openwisp2_usage_metric_collection_periodic_tasks: true - # this role provides a default configuration of freeradius - # if you manage freeradius on a different machine or you need different configurations - # you can disable this default behavior - openwisp2_freeradius_install: true - # Set an account to expire T seconds after first login. - # This variable sets the value of T. - freeradius_expire_attr_after_seconds: 86400 - freeradius_dir: /etc/freeradius/3.0 - freeradius_mods_available_dir: "{{ freeradius_dir }}/mods-available" - freeradius_mods_enabled_dir: "{{ freeradius_dir }}/mods-enabled" - freeradius_sites_available_dir: "{{ freeradius_dir }}/sites-available" - freeradius_sites_enabled_dir: "{{ freeradius_dir }}/sites-enabled" - freeradius_rest: - url: "https://{{ inventory_hostname }}/api/v1/freeradius" - freeradius_safe_characters: "+@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /" - # Sets the source path of the template that contains freeradius site configuration. - # Defaults to "templates/freeradius/openwisp_site.j2" shipped in the role. - freeradius_openwisp_site_template_src: custom_freeradius_site.j2 - # Whether to deploy the default openwisp_site for FreeRADIUS. - # Defaults to true. - freeradius_deploy_openwisp_site: false - # FreeRADIUS listen address for the openwisp_site. - # Defaults to "*", i.e. listen on all interfaces. - freeradius_openwisp_site_listen_ipaddr: "10.8.0.1" - # A list of dict that includes organization's name, UUID, RADIUS token, - # TLS configuration, and ports for authentication, accounting, and inner tunnel. - # This list of dict is used to generate FreeRADIUS sites that support - # WPA Enterprise (EAP-TTLS-PAP) authentication. - # Defaults to an empty list. - freeradius_eap_orgs: - # The name should not contain spaces or special characters - - name: openwisp - # UUID of the organization can be retrieved from the OpenWISP admin - uuid: 00000000-0000-0000-0000-000000000000 - # Radius token of the organization can be retrieved from the OpenWISP admin - radius_token: secret-radius-token - # Port used by the authentication service for this FreeRADIUS site - auth_port: 1832 - # Port used by the accounting service for this FreeRADIUS site - acct_port: 1833 - # Port used by the authentication service of inner tunnel for this FreeRADIUS site - inner_tunnel_auth_port: 18330 - # CA certificate for the FreeRADIUS site - ca: /etc/freeradius/certs/ca.crt - # TLS certificate for the FreeRADIUS site - cert: /etc/freeradius/certs/cert.pem - # TLS private key for the FreeRADIUS site - private_key: /etc/freeradius/certs/key.pem - # Diffie-Hellman key for the FreeRADIUS site - dh: /etc/freeradius/certs/dh - # Extra instructions for the "tls-config" section of the EAP module - # for the FreeRADIUS site - tls_config_extra: | - private_key_password = whatever - ecdh_curve = "prime256v1" - # Sets the source path of the template that contains freeradius site configuration - # for WPA Enterprise (EAP-TTLS-PAP) authentication. - # Defaults to "templates/freeradius/eap/openwisp_site.j2" shipped in the role. - freeradius_eap_openwisp_site_template_src: custom_eap_openwisp_site.j2 - # Sets the source path of the template that contains freeradius inner tunnel - # configuration for WPA Enterprise (EAP-TTLS-PAP) authentication. - # Defaults to "templates/freeradius/eap/inner_tunnel.j2" shipped in the role. - freeradius_eap_inner_tunnel_template_src: custom_eap_inner_tunnel.j2 - # Sets the source path of the template that contains freeradius EAP configuration - # for WPA Enterprise (EAP-TTLS-PAP) authentication. - # Defaults to "templates/freeradius/eap/eap.j2" shipped in the role. - freeradius_eap_template_src: custom_eap.j2 - cron_delete_old_notifications: "'hour': 0, 'minute': 0" - cron_deactivate_expired_users: "'hour': 0, 'minute': 5" - cron_delete_old_radiusbatch_users: "'hour': 0, 'minute': 10" - cron_cleanup_stale_radacct: "'hour': 0, 'minute': 20" - cron_delete_old_postauth: "'hour': 0, 'minute': 30" - cron_delete_old_radacct: "'hour': 1, 'minute': 30" - cron_password_expiration_email: "'hour': 1, 'minute': 0" - cron_unverify_inactive_users: "'hour': 1, 'minute': 45" - cron_delete_inactive_users: "'hour': 1, 'minute': 55" - # cross-origin resource sharing (CORS) settings - # https://pypi.org/project/django-cors-headers/ - openwisp2_django_cors: - # Setting this to "true" will install the django-cors-headers package - # and configure the Django middleware setting to support CORS. - # By default, it is set to false. - enabled: true - # Configures "CORS_ALLOWED_ORIGINS" setting of the django-cors-headers - # package. A list of origins that are authorized to make cross-site - # HTTP requests. Read https://github.com/adamchainz/django-cors-headers#cors_allowed_origins-sequencestr - # for detail. By default, it is set to an empty list. - allowed_origins_list: ["https://log.openwisp.org"] - # Configures "CORS_REPLACE_HTTPS_REFERER" setting of the django-cors-headers - # package. Read https://github.com/adamchainz/django-cors-headers#cors_replace_https_referer-bool - # for detail. Setting this to "true" will also configure the - # Django middleware setting to add "CorsPostCsrfMiddleware". - # By default, it is set to false. - replace_https_referer: true -``` - -**Note**: The default values for settings provided to control the number of process and threads -of uWSGI and Daphne are set conservatively. It is expected from user to update these settings -to suit scale of their project. The same thing applies for concurrency and autoscale settings -for celery workers. - -Support -======= - -See [OpenWISP Support Channels](http://openwisp.org/support.html). diff --git a/README.rst b/README.rst new file mode 100644 index 00000000..ec81a0c3 --- /dev/null +++ b/README.rst @@ -0,0 +1,32 @@ +ansible-openwisp2 +================= + +.. image:: https://github.com/openwisp/ansible-openwisp2/workflows/Ansible%20OpenWISP2%20CI%20Build/badge.svg?branch=master + :target: https://github.com/openwisp/ansible-openwisp2/actions?query=workflow%3A%22Ansible+OpenWISP2+CI+Build%22 + :alt: Build Status + +.. image:: http://img.shields.io/badge/galaxy-openwisp.openwisp2-blue.svg?style=flat-square + :target: https://galaxy.ansible.com/ui/standalone/roles/openwisp/openwisp2/ + :alt: Galaxy + +.. image:: https://img.shields.io/gitter/room/nwjs/nw.js.svg + :target: https://gitter.im/openwisp/general + :alt: Chat + +Ansible role that installs the OpenWISP Server Application. + +Tested on **Debian (Bookworm/Bullseye)**, **Ubuntu (24/22/20 LTS)**. + +**Recommended minimum ansible core version**: 2.13. + +Documentation +------------- + +- `Developer documentation + `_ +- `User documentation `_ + +Support +------- + +See `OpenWISP Support Channels `__. diff --git a/docs/developer/installation.rst b/docs/developer/installation.rst new file mode 100644 index 00000000..22a57a2a --- /dev/null +++ b/docs/developer/installation.rst @@ -0,0 +1,100 @@ +Developer Installation instructions +=================================== + +.. include:: ../partials/developer-docs.rst + +.. contents:: **Table of Contents**: + :depth: 2 + :local: + +Installing for Development +-------------------------- + +First of all, create the directory where you want to place the +repositories of the ansible roles and create directory roles. + +.. code-block:: bash + + mkdir -p ~/openwisp-dev/roles + cd ~/openwisp-dev/roles + +Clone ``ansible-openwisp2`` and ``Stouts.postfix`` as follows: + +.. code-block:: bash + + git clone https://github.com/openwisp/ansible-openwisp2.git openwisp.openwisp2 + git clone https://github.com/Stouts/Stouts.postfix + git clone https://github.com/openwisp/ansible-ow-influxdb openwisp.influxdb + +Now, go to the parent directory & create hosts file and playbook.yml: + +.. code-block:: bash + + cd ../ + touch hosts + touch playbook.yml + +From here on you can follow the instructions available at the following +sections: + +- :ref:`ansible_install` +- :ref:`ansible_create_inventory_file` +- :ref:`ansible_create_playbook_file` +- :ref:`ansible_run_playbook` + +All done! + +How to Run Tests +---------------- + +If you want to contribute to ``ansible-openwisp2`` you should run tests in +your development environment to ensure your changes are not breaking +anything. + +To do that, proceed with the following steps: + +**Step 1**: Clone ``ansible-openwisp2`` + +Clone repository by: + +.. code-block:: shell + + git clone https://github.com//ansible-openwisp2.git openwisp.openwisp2 + cd openwisp.openwisp2 + +**Step 2**: Install docker + +If you haven't installed docker yet, you need to install it (example for +linux debian/ubuntu systems): + +.. code-block:: shell + + sudo apt install docker.io + +**Step 3**: Install molecule and dependencies + +.. code-block:: shell + + pip install molecule[docker] molecule-plugins yamllint ansible-lint docker + +**Step 4**: Download docker images + +.. code-block:: shell + + docker pull geerlingguy/docker-ubuntu2204-ansible:latest + docker pull geerlingguy/docker-ubuntu2004-ansible:latest + docker pull geerlingguy/docker-debian11-ansible:latest + +**Step 5**: Run molecule test + +.. code-block:: shell + + molecule test -s local + +If you don't get any error message it means that the tests ran +successfully without errors. + +.. important:: + + **Pro Tip:** Use ``molecule test --destroy=never`` to speed up + subsequent test runs. diff --git a/docs/images/architecture-v2-ansible-openwisp.png b/docs/images/architecture-v2-ansible-openwisp.png new file mode 100644 index 00000000..e9fe7f2f Binary files /dev/null and b/docs/images/architecture-v2-ansible-openwisp.png differ diff --git a/docs/debian-software-selection.png b/docs/images/debian-software-selection.png similarity index 100% rename from docs/debian-software-selection.png rename to docs/images/debian-software-selection.png diff --git a/docs/host-only-network.png b/docs/images/host-only-network.png similarity index 100% rename from docs/host-only-network.png rename to docs/images/host-only-network.png diff --git a/docs/install-openwisp2.png b/docs/images/install-openwisp2.png similarity index 100% rename from docs/install-openwisp2.png rename to docs/images/install-openwisp2.png diff --git a/docs/openwisp2-modules-diagram.png b/docs/images/openwisp2-modules-diagram.png similarity index 100% rename from docs/openwisp2-modules-diagram.png rename to docs/images/openwisp2-modules-diagram.png diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 00000000..d02f960b --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,51 @@ +Ansible OpenWISP +================ + +.. seealso:: + + **Source code**: `github.com/openwisp/ansible-openwisp2 + `_. + +This ansible role allows deploying the OpenWISP Server Application. + +**Recommended minimum ansible core version**: 2.13. + +Tested on **Debian (Bookworm/Bullseye)**, **Ubuntu (24/22/20 LTS)**. + +The following diagram illustrates the role of the Ansible OpenWISP role +within the OpenWISP architecture. + +.. figure:: images/architecture-v2-ansible-openwisp.png + :target: ../_images/architecture-v2-ansible-openwisp.png + :align: center + :alt: OpenWISP Architecture: Ansible OpenWISP role + + **OpenWISP Architecture: highlighted Ansible OpenWISP role** + +.. important:: + + For an enhanced viewing experience, open the image above in a new + browser tab. + + Refer to :doc:`/general/architecture` for more information. + +.. toctree:: + :caption: Ansible OpenWISP Usage Docs + :maxdepth: 1 + + ./user/system-requirements.rst + ./user/quickstart.rst + ./user/certbot-ssl.rst + ./user/enabling-modules.rst + ./user/deploying-wpa-eap-ttls-pap.rst + ./user/deploying-custom-static-content.rst + ./user/configuring-cors-headers.rst + ./user/installing-on-vm.rst + ./user/troubleshooting.rst + ./user/role-variables.rst + +.. toctree:: + :caption: Ansible OpenWISP Developer Docs + :maxdepth: 1 + + ./developer/installation.rst diff --git a/docs/partials/developer-docs.rst b/docs/partials/developer-docs.rst new file mode 100644 index 00000000..76dede26 --- /dev/null +++ b/docs/partials/developer-docs.rst @@ -0,0 +1,12 @@ +.. note:: + + This documentation page is aimed at developers who want to customize, + change or extend the code of Ansible OpenWISP2 in order to modify its + behavior (eg: for personal or commercial purposes or to fix a bug, + implement a new feature or contribute to the project in general). + + If you aren't a developer and you are looking for information on how + to use OpenWISP, please refer to: + + - :doc:`General OpenWISP Quickstart ` + - :doc:`Ansible OpenWISP2 User Docs ` diff --git a/docs/user/certbot-ssl.rst b/docs/user/certbot-ssl.rst new file mode 100644 index 00000000..42600a12 --- /dev/null +++ b/docs/user/certbot-ssl.rst @@ -0,0 +1,65 @@ +Using Let's Encrypt SSL Certificate +=================================== + +This section explains how to **automatically install and renew a valid SSL +certificate** signed by `Let's Encrypt `__. + +The first thing you have to do is to setup a valid domain for your +OpenWISP instance, this means your inventory file (hosts) should look like +the following: + +.. code-block:: text + + [openwisp2] + openwisp2.yourdomain.com + +You must be able to add a DNS record for ``openwisp2.yourdomain.com``, you +cannot use an ip address in place of ``openwisp2.yourdomain.com``. + +Once your domain is set up and the DNS record is propagated, proceed by +installing the ansible role `geerlingguy.certbot +`__: + +.. code-block:: shell + + ansible-galaxy install geerlingguy.certbot + +Then proceed to edit your ``playbook.yml`` so that it will look similar to +the following example: + +.. code-block:: yaml + + - hosts: openwisp2 + become: "{{ become | default('yes') }}" + roles: + - geerlingguy.certbot + - openwisp.openwisp2 + vars: + # SSL certificates + openwisp2_ssl_cert: "/etc/letsencrypt/live/{{ inventory_hostname }}/fullchain.pem" + openwisp2_ssl_key: "/etc/letsencrypt/live/{{ inventory_hostname }}/privkey.pem" + + # certbot configuration + certbot_auto_renew_minute: "20" + certbot_auto_renew_hour: "5" + certbot_create_if_missing: true + certbot_auto_renew_user: "" + certbot_certs: + - email: "" + domains: + - "{{ inventory_hostname }}" + pre_tasks: + - name: Update APT package cache + apt: + update_cache: true + changed_when: false + retries: 5 + delay: 10 + register: result + until: result is success + +Read the `documentation of geerlingguy.certbot +`__ to learn +more about configuration of certbot role. + +Once you have set up all the variables correctly, run the playbook again. diff --git a/docs/user/configuring-cors-headers.rst b/docs/user/configuring-cors-headers.rst new file mode 100644 index 00000000..7bf84128 --- /dev/null +++ b/docs/user/configuring-cors-headers.rst @@ -0,0 +1,73 @@ +Configuring CORS Headers +======================== + +While integrating OpenWISP with external services, you can run into issues +related to `CORS (Cross-Origin Resource Sharing) +`__. This role +allows users to configure the CORS headers with the help of +`django-cors-headers +`__ package. Here's a +short summary of how to do this: + +**Step 1**: :ref:`Install ansible ` + +**Step 2**: :ref:`Install this role ` + +**Step 3**: :ref:`Create inventory file ` + +**Step 4**: Create a playbook file with following contents: + +.. code-block:: yaml + + - hosts: openwisp2 + become: "{{ become | default('yes') }}" + roles: + - openwisp.openwisp2 + vars: + # Cross-Origin Resource Sharing (CORS) settings + openwisp2_django_cors: + enabled: true + allowed_origins_list: + - https://frontend.openwisp.org + - https://logs.openwisp.org + +**Note:** to learn about the supported fields of the +``openwisp2_django_cors`` variable, look for the word +“openwisp2_django_cors” in the :doc:`role-variables` section of this +document. + +**Step 5**: :ref:`Run the playbook ` + +When the playbook is done running, if you got no errors you can login at +https://openwisp2.mydomain.com/admin, with the following credentials: + +.. code-block:: text + + username: admin + password: admin + +The ansible-openwisp2 only provides abstraction (variables) for handful of +settings available in `django-cors-headers +`__ module. Use the +``openwisp2_extra_django_settings_instructions`` or +``openwisp2_extra_django_settings`` variable to configure additional +setting of ``django-cors-headers`` as shown in the following example: + +.. code-block:: yaml + + - hosts: openwisp2 + become: "{{ become | default('yes') }}" + roles: + - openwisp.openwisp2 + vars: + openwisp2_django_cors: + enabled: true + allowed_origins_list: + - https://frontend.openwisp.org + - https://logs.openwisp.org + replace_https_referer: true + # Configuring additional settings for django-cors-headers + openwisp2_extra_django_settings_instructions: + - | + CORS_ALLOW_CREDENTIALS = True + CORS_ALLOW_ALL_ORIGINS = True diff --git a/docs/user/deploying-custom-static-content.rst b/docs/user/deploying-custom-static-content.rst new file mode 100644 index 00000000..e5844828 --- /dev/null +++ b/docs/user/deploying-custom-static-content.rst @@ -0,0 +1,14 @@ +Deploying Custom Static Content +=============================== + +For deploying custom static content (HTML files, etc.) add all the static +content in ``files/ow2_static`` directory. The files inside +``files/ow2_static`` will be uploaded to a directory named +``static_custom`` in ``openwisp2_path``. + +This is helpful for :ref:`customizing OpenWISP's theme +`. + +E.g., if you added a custom CSS file in +``files/ow2_static/css/custom.css``, the file location to use in +:ref:`openwisp_admin_theme_links` setting will be ``css/custom.css``. diff --git a/docs/user/deploying-wpa-eap-ttls-pap.rst b/docs/user/deploying-wpa-eap-ttls-pap.rst new file mode 100644 index 00000000..ea3b548d --- /dev/null +++ b/docs/user/deploying-wpa-eap-ttls-pap.rst @@ -0,0 +1,175 @@ +Configuring FreeRADIUS for WPA Enterprise (EAP-TTLS-PAP) +======================================================== + +You can use OpenWISP RADIUS for setting up WPA Enterprise (EAP-TTLS-PAP) +authentication. This allows to authenticate on WiFi networks using Django +user credentials. Prior to proceeding, ensure you've reviewed the tutorial +on :doc:`/tutorials/wpa-enterprise-eap-ttls-pap`. This documentation +section complements the tutorial and focuses solely on demonstrating the +ansible role's capabilities to configure FreeRADIUS. + +.. important:: + + The ansible role supports OpenWISP's multi-tenancy by creating + individual FreeRADIUS sites for each organization. You must include + configuration details for **each organization** that will use WPA + Enterprise. + +Here's an example playbook which enables OpenWISP RADIUS module, installs +FreeRADIUS, and configures it for WPA Enterprise (EAP-TTLS-PAP): + +.. code-block:: yaml + + - hosts: openwisp2 + become: "{{ become | default('yes') }}" + roles: + - openwisp.openwisp2 + vars: + openwisp2_radius: true + openwisp2_freeradius_install: true + # Define a list of dictionaries detailing each organization's + # name, UUID, RADIUS token, and ports for authentication, + # accounting, and the inner tunnel. These details will be used + # to create FreeRADIUS sites tailored for WPA Enterprise + # (EAP-TTLS-PAP) authentication per organization. + freeradius_eap_orgs: + # A reference name for the organization, + # used in FreeRADIUS configurations. + # Don't use spaces or special characters. + - name: openwisp + # UUID of the organization. + # You can retrieve this from the organization admin + # in the OpenWISP web interface. + uuid: 00000000-0000-0000-0000-000000000000 + # Radius token of the organization. + # You can retrieve this from the organization admin + # in the OpenWISP web interface. + radius_token: secret-radius-token + # Port used by the authentication service for + # this FreeRADIUS site + auth_port: 1822 + # Port used by the accounting service for this FreeRADIUS site + acct_port: 1823 + # Port used by the authentication service of inner tunnel + # for this FreeRADIUS site + inner_tunnel_auth_port: 18230 + # If you want to use a custom certificate for FreeRADIUS + # EAP module, you can specify the path to the CA, server + # certificate, and private key, and DH key as follows. + # Ensure that these files can be read by the "freerad" user. + cert: /etc/freeradius/certs/cert.pem + private_key: /etc/freeradius/certs/key.pem + ca: /etc/freeradius/certs/ca.crt + dh: /etc/freeradius/certs/dh + tls_config_extra: | + private_key_password = whatever + ecdh_curve = "prime256v1" + # You can add as many organizations as you want + - name: demo + uuid: 00000000-0000-0000-0000-000000000001 + radius_secret: demo-radius-token + auth_port: 1832 + acct_port: 1833 + inner_tunnel_auth_port: 18330 + # If you omit the certificate fields, + # the FreeRADIUS site will use the default certificates + # located in /etc/freeradius/certs. + +In the example above, custom ports 1822, 1823, and 18230 are utilized for +FreeRADIUS authentication, accounting, and inner tunnel authentication, +respectively. These custom ports are specified because the Ansible role +creates a common FreeRADIUS site for all organizations, which also +supports captive portal functionality. This common site is configured to +listen on the default FreeRADIUS ports 1812, 1813, and 18120. Therefore, +when configuring WPA Enterprise authentication for each organization, +unique ports must be provided to ensure proper isolation and +functionality. + +Using Let's Encrypt Certificate for WPA Enterprise (EAP-TTLS-PAP) +----------------------------------------------------------------- + +In this section, we demonstrate how to utilize Let's Encrypt certificates +for WPA Enterprise (EAP-TTLS-PAP) authentication. Similar to the +:doc:`./certbot-ssl`, we use `geerlingguy.certbot +`_ role to automatically +install and renew a valid SSL certificate. + +The following example playbook achieves the following goals: + +- Provision a separate Let's Encrypt certificate for the + `freeradius.yourdomain.com` hostname. This certificate will be utilized + by the FreeRADIUS site for WPA Enterprise authentication. +- Create a renewal hook to set permissions on the generated certificate so + the FreeRADIUS server can read it. + +.. note:: + + You can also use the same SSL certificate for both Nginx and + FreeRADIUS, but it's crucial to understand the security implications. + Please exercise caution and refer to the example playbook comments for + guidance. + +.. code-block:: yaml + + - hosts: openwisp2 + become: "{{ become | default('yes') }}" + roles: + - geerlingguy.certbot + - openwisp.openwisp2 + vars: + # certbot configuration + certbot_auto_renew_minute: "20" + certbot_auto_renew_hour: "5" + certbot_create_if_missing: true + certbot_auto_renew_user: "" + certbot_certs: + - email: "" + domains: + - "{{ inventory_hostname }}" + # If you choose to re-use the same certificate for both services, + # you can omit the following item in your playbook. + - email: "" + domains: + - "freeradius.yourdomain.com" + # Configuration to use Let's Encrypt certificate for OpenWISP server (Nnginx) + openwisp2_ssl_cert: "/etc/letsencrypt/live/{{ inventory_hostname }}/fullchain.pem" + openwisp2_ssl_key: "/etc/letsencrypt/live/{{ inventory_hostname }}/privkey.pem" + # Configuration for openwisp-radius + openwisp2_radius: true + openwisp2_freeradius_install: true + freeradius_eap_orgs: + - name: demo + uuid: 00000000-0000-0000-0000-000000000001 + radius_secret: demo-radius-token + auth_port: 1832 + acct_port: 1833 + inner_tunnel_auth_port: 18330 + # Update the cert_file and private_key paths to point to the + # Let's Encrypt certificate. + cert: /etc/letsencrypt/live/freeradius.yourdomain.com/fullchain.pem + private_key: /etc/letsencrypt/live/freeradius.yourdomain.com/privkey.pem + # If you choose to re-use the same certificate for both services, + # your configuration would look like this + # cert: /etc/letsencrypt/live/{{ inventory_hostname }}/fullchain.pem + # private_key: /etc/letsencrypt/live/{{ inventory_hostname }}/privkey.pem + tasks: + # Tasks to ensure the Let's Encrypt certificate can be read by the FreeRADIUS server. + # If you are using the same certificate for both services, you need to + # replace "freeradius.yourdomain.com" with "{{ inventory_hostname }}" + # in the following task. + - name: "Create a renewal hook for setting permissions on /etc/letsencrypt/live/freeradius.yourdomain.com" + copy: + content: | + #!/bin/bash + chown -R root:freerad /etc/letsencrypt/live/ /etc/letsencrypt/archive/ + chmod 0750 /etc/letsencrypt/live/ /etc/letsencrypt/archive/ + chmod -R 0640 /etc/letsencrypt/archive/freeradius.yourdomain.com/ + chmod 0750 /etc/letsencrypt/archive/freeradius.yourdomain.com/ + dest: /etc/letsencrypt/renewal-hooks/post/chown_freerad + owner: root + group: root + mode: '0700' + register: chown_freerad_result + - name: Change the ownership of the certificate files + when: chown_freerad_result.changed + command: /etc/letsencrypt/renewal-hooks/post/chown_freerad diff --git a/docs/user/enabling-modules.rst b/docs/user/enabling-modules.rst new file mode 100644 index 00000000..dd2cf725 --- /dev/null +++ b/docs/user/enabling-modules.rst @@ -0,0 +1,164 @@ +Enabling OpenWISP Modules +========================= + +.. contents:: **Table of Contents**: + :depth: 3 + :local: + +Enabling the Monitoring Module +------------------------------ + +The :doc:`Monitoring module ` is enabled by default, it +can be disabled by setting ``openwisp2_monitoring`` to ``false``. + +Enabling the Firmware Upgrader Module +------------------------------------- + +It is encouraged that you read the :doc:`quick-start guide of +openwisp-firmware-upgrader ` before +going ahead. + +To enable the :doc:`Firmware Upgrader ` module +you need to set ``openwisp2_firmware_upgrader`` to ``true`` in your +``playbook.yml`` file. Here's a short summary of how to do this: + +**Step 1**: :ref:`Install ansible ` + +**Step 2**: :ref:`Install this role ` + +**Step 3**: :ref:`Create inventory file ` + +**Step 4**: Create a playbook file with following contents: + +.. code-block:: yaml + + - hosts: openwisp2 + become: "{{ become | default('yes') }}" + roles: + - openwisp.openwisp2 + vars: + openwisp2_firmware_upgrader: true + +**Step 5**: :ref:`Run the playbook ` + +When the playbook is done running, if you got no errors you can login at +https://openwisp2.mydomain.com/admin with the following credentials: + +.. code-block:: text + + username: admin + password: admin + +You can configure :doc:`openwisp-firmware-upgrader specific settings +` using the +``openwisp2_extra_django_settings`` or +``openwisp2_extra_django_settings_instructions``. + +E.g: + +.. code-block:: yaml + + - hosts: openwisp2 + become: "{{ become | default('yes') }}" + roles: + - openwisp.openwisp2 + vars: + openwisp2_firmware_upgrader: true + openwisp2_extra_django_settings_instructions: + - | + OPENWISP_CUSTOM_OPENWRT_IMAGES = ( + ('my-custom-image-squashfs-sysupgrade.bin', { + 'label': 'My Custom Image', + 'boards': ('MyCustomImage',) + }), + ) + +Refer the :doc:`role-variables` section of the documentation for a +complete list of available role variables. + +Enabling the Network Topology Module +------------------------------------ + +To enable the :doc:`Network Topology module ` you +need to set ``openwisp2_network_topology`` to ``true`` in your +``playbook.yml`` file. Here's a short summary of how to do this: + +**Step 1**: :ref:`Install ansible ` + +**Step 2**: :ref:`Install this role ` + +**Step 3**: :ref:`Create inventory file ` + +**Step 4**: Create a playbook file with following contents: + +.. code-block:: yaml + + - hosts: openwisp2 + become: "{{ become | default('yes') }}" + roles: + - openwisp.openwisp2 + vars: + openwisp2_network_topology: true + +**Step 5**: :ref:`Run the playbook ` + +When the playbook is done running, if you got no errors you can login at +https://openwisp2.mydomain.com/admin with the following credentials: + +.. code-block:: text + + username: admin + password: admin + +.. _ansible_enabling_radius_module: + +Enabling the RADIUS Module +-------------------------- + +To enable the :doc:`RADIUS module ` you need to set +``openwisp2_radius`` to ``true`` in your ``playbook.yml`` file. Here's a +short summary of how to do this: + +**Step 1**: :ref:`Install ansible ` + +**Step 2**: :ref:`Install this role ` + +**Step 3**: :ref:`Create inventory file ` + +**Step 4**: Create a playbook file with following contents: + +.. code-block:: yaml + + - hosts: openwisp2 + become: "{{ become | default('yes') }}" + roles: + - openwisp.openwisp2 + vars: + openwisp2_radius: true + openwisp2_freeradius_install: true + # set to false when you don't want to register openwisp-radius + # API endpoints. + openwisp2_radius_urls: true + +.. note:: + + ``openwisp2_freeradius_install`` option provides a basic configuration + of freeradius for OpenIWSP, it sets up the `radius user token + mechanism + `__ + if you want to use another mechanism or manage your freeradius + separately, please disable this option by setting it to ``false``. + +**Step 5**: :ref:`Run the playbook ` + +When the playbook is done running, if you got no errors you can login at: + +.. code-block:: + + https://openwisp2.mydomain.com/admin + username: admin + password: admin + +**Note:** for more information regarding radius configuration options, +look for the word “radius” in the :doc:`role-variables` section of this +document. diff --git a/docs/user/installing-on-vm.rst b/docs/user/installing-on-vm.rst new file mode 100644 index 00000000..a43bd724 --- /dev/null +++ b/docs/user/installing-on-vm.rst @@ -0,0 +1,143 @@ +Install OpenWISP for Testing in a VirtualBox VM +=============================================== + +If you want to try out OpenWISP in your own development environment, the +safest way is to use a VirtualBox Virtual Machine (from here on VM). + +.. contents:: **Table of Contents**: + :depth: 2 + :local: + +Using Vagrant +------------- + +**Since August 2018 there's a new fast and easy way to install OpenWISP +for testing purposes** leveraging `Vagrant `__, +a popular open source tool for building and maintaining portable virtual +software development environments. + +To use this new way, clone the repository `vagrant-openwisp2 +`__, it contains the +instructions (in the ``README.md``) and the vagrant configuration to +perform the automatic installation. + +Alternatively, you can read on to learn how to install *VirtualBox* and +run *ansible-openwisp2* manually, this is useful if you need to test +advanced customizations of *OpenWISP*. + +Installing Debian 11 on VirtualBox +---------------------------------- + +Install `VirtualBox `__ and create a new Virtual +Machine running Debian 11. A step-by-step guide is available `here +`__, +however we need to change a few things to get ansible working. + +VM Configuration +---------------- + +Proceed with the installation as shown in the guide linked above, and come +back here when you see this screen: + +.. figure:: ../images/debian-software-selection.png + :target: ../../_images/debian-software-selection.png + :alt: Screenshot of the Software Selection screen + +We're only running this as a server, so you can uncheck ``Debian desktop +environment``. Make sure ``SSH server`` and ``standard system utilities`` +are checked. + +Next, add a `Host-only Network Adapter +`__ and +assign an IP address to the VM. + +- On the Main VirtualBox page, Go to ``File > Host Network Manager`` +- Click the + icon to create a new adapter +- Set the IPv4 address to ``192.168.56.1`` and the IPv4 Network Mask to + ``255.255.255.0``. You may need to select ``Configure Adapter Manually`` + to do this. The IPv6 settings can be ignored + + .. image:: ../images/host-only-network.png + :target: ../../_images/host-only-network.png + :alt: Screenshot of the Host-only network configuration screen + +- Shut off your VM +- In your VM settings, in the Network section, click Adapter 2 and Enable + this Adapter +- Select Host-only adapter and the name of the adapter you created +- Boot up your VM, run ``su``, and type in your superuser password +- Run ``ls /sys/class/net`` and take note of the output +- Run ``nano /etc/network/interfaces`` and add the following at the end of + the file: + + .. code-block:: text + + auto enp0s8 + iface enp0s8 inet static + address 192.168.56.2 + netmask 255.255.255.0 + network 192.168.56.0 + broadcast 192.168.56.255 + + Replace ``enp0s8`` with the network interface not present in the file + but is shown when running ``ls /sys/class/net`` + +- Save the file with CtrlO then Enter, and exit with CtrlX +- Restart the machine by running ``reboot`` + +Make sure you can access your VM via ssh: + +.. code-block:: shell + + ssh 192.168.56.2 + +Back to your local machine +-------------------------- + +Proceed with these steps in your **local machine**, not the VM. + +**Step 1**: :ref:`Install ansible ` + +**Step 2**: :ref:`Install the OpenWISP2 role for Ansible +` + +**Step 3**: :ref:`Set up a working directory +` + +**Step 4**: Create the ``hosts`` file + +Create an ansible inventory file named ``hosts`` **in your working +directory** (i.e. not in the VM) with the following contents: + +.. code-block:: + + [openwisp2] + 192.168.56.2 + +**Step 5**: Create the ansible playbook + +In the same directory where you created the ``host`` file, create a file +named ``playbook.yml`` which contains the following: + +.. code-block:: yaml + + - hosts: openwisp2 + roles: + - openwisp.openwisp2 + # the following line is needed only when an IP address is used as the inventory hostname + vars: + postfix_myhostname: localhost + +**Step 6**: Run the playbook + +.. code-block:: shell + + ansible-playbook -i hosts playbook.yml -b -k -K --become-method=su + +When the playbook ran successfully, you can log in at +``https://192.168.56.2/admin`` with the following credentials: + +.. code-block:: text + + username: admin + password: admin diff --git a/docs/user/quickstart.rst b/docs/user/quickstart.rst new file mode 100644 index 00000000..e73932a0 --- /dev/null +++ b/docs/user/quickstart.rst @@ -0,0 +1,333 @@ +Deploying OpenWISP Using Ansible +================================ + +.. contents:: **Table of Contents**: + :depth: 3 + :local: + +Introduction & Prerequisites +---------------------------- + +.. note:: + + If you want to use the latest features of OpenWISP, refer to + :ref:`ansible_deploying_development_version`. + +.. raw:: html + +

+ +

+ +If you don't know how to use ansible, don't panic, this procedure will +guide you towards a fully working basic OpenWISP installation. + +If you already know how to use ansible, you can skip this tutorial. + +First of all you need to understand two key concepts: + +- for **“production server”** we mean a server (**not a laptop or a + desktop computer!**) with public IpV4 / IPv6 which is used to host + OpenWISP +- for **“local machine”** we mean the host from which you launch ansible, + eg: your own laptop + +Ansible is a configuration management tool that works by entering +production servers via SSH, **so you need to install it and configure it +on the machine where you launch the deployment** and this machine must be +able to SSH into the production server. + +Ansible will be run on your local machine and from there it will connect +to the production server to install OpenWISP. + +.. note:: + + It is recommended to use this procedure on clean virtual machines or + linux containers. + + If you are trying to install OpenWISP on your laptop or desktop pc + just for testing purposes, please read :doc:`Install OpenWISP for + testing in a VirtualBox VM <./installing-on-vm>`. + +.. _ansible_install: + +Install Ansible +--------------- + +Install ansible (minimum recommended version 2.13) **on your local +machine** (not the production server!) if you haven't done already. + +We suggest following the `ansible installation guide +`__. +to install ansible. It is recommended to install ansible through a virtual +environment to avoid dependency issues. + +Please ensure that you have the correct version of Jinja installed in your +Python environment: ``pip install Jinja2>=2.11`` + +.. _ansible_install_role: + +Install This Role +----------------- + +For the sake of simplicity, the easiest thing is to install this role **on +your local machine** via ``ansible-galaxy`` (which was installed when +installing ansible), therefore run: + +.. code-block:: shell + + ansible-galaxy install openwisp.openwisp2 + +Ensure that you have the `community.general +`_ +and `ansible.posix +`_ +collections installed and up to date: + +.. code-block:: shell + + ansible-galaxy collection install "community.general:>=3.6.0" + ansible-galaxy collection install "ansible.posix" + +.. _ansible_choose_working_directory: + +Choose a Working Directory +-------------------------- + +Choose a working directory **on your local machine** where to put the +configuration of OpenWISP. + +This will be useful when you will need to upgrade OpenWISP. + +Eg: + +.. code-block:: shell + + mkdir ~/openwisp2-ansible-playbook + cd ~/openwisp2-ansible-playbook + +.. _ansible_create_inventory_file: + +Create Inventory File +--------------------- + +The inventory file is where group of servers are defined. In our simple +case we will define just one group in which we will put just one server. + +Create a new file called ``hosts`` in the working directory **on your +local machine** (the directory just created in the previous step), with +the following contents: + +.. code-block:: text + + [openwisp2] + openwisp2.mydomain.com + +Substitute ``openwisp2.mydomain.com`` with your **production server**'s +hostname - **DO NOT REPLACE ``openwisp2.mydomain.com`` WITH AN IP +ADDRESS**, otherwise email sending through postfix will break, causing 500 +internal server errors on some operations. + +.. _ansible_create_playbook_file: + +Create Playbook File +-------------------- + +Create a new playbook file ``playbook.yml`` **on your local machine** with +the following contents: + +.. code-block:: yaml + + - hosts: openwisp2 + become: "{{ become | default('yes') }}" + roles: + - openwisp.openwisp2 + vars: + openwisp2_default_from_email: "openwisp2@openwisp2.mydomain.com" + +The line ``become: "{{ become | default('yes') }}"`` means ansible will +use the ``sudo`` program to run each command. You may remove this line if +you don't need it (eg: if you are ``root`` user on the production server). + +You may replace ``openwisp2`` on the ``hosts`` field with your production +server's hostname if you desire. + +Substitute ``openwisp2@openwisp2.mydomain.com`` with what you deem most +appropriate as default sender for emails sent by OpenWISP 2. + +.. _ansible_run_playbook: + +Run the Playbook +---------------- + +Now is time to **deploy OpenWISP to the production server**. + +Run the playbook **from your local machine** with: + +.. code-block:: shell + + ansible-playbook -i hosts playbook.yml -u -k --become -K + +Substitute ```` with your **production server**'s username. + +The ``-k`` argument will need the ``sshpass`` program. + +You can remove ``-k``, ``--become`` and ``-K`` if your public SSH key is +installed on the server. + +.. tip:: + + - If you have an error like ``Authentication or permission failure`` + then try to use *root* user ``ansible-playbook -i hosts playbook.yml + -u root -k`` + - If you have an error about adding the host's fingerprint to the + ``known_hosts`` file, you can simply connect to the host via SSH and + answer yes when prompted; then you can run ``ansible-playbook`` + again. + +When the playbook is done running, if you got no errors you can login at +``https://openwisp2.mydomain.com/admin`` with the following credentials: + +.. code-block:: text + + username: admin + password: admin + +Substitute ``openwisp2.mydomain.com`` with your production server's +hostname. + +Now proceed with the following steps: + +1. change the password (and the username if you like) of the superuser as + soon as possible +2. update the ``name`` field of the default ``Site`` object to accurately + display site name in email notifications +3. edit the information of the default organization +4. in the default organization you just updated, note down the + automatically generated *shared secret* option, you will need it to use + the :doc:`auto-registration feature of openwisp-config + ` +5. this Ansible role creates a default template to update + ``authorized_keys`` on networking devices using the default access + credentials. The role will either use an existing SSH key pair or + create a new one if no SSH key pair exists on the host machine. + +Now you are ready to start configuring your network! **If you need help** +you can ask questions on one of the official `OpenWISP Support Channels +`__. + +Upgrading OpeNWISP +------------------ + +.. important:: + + It is strongly recommended to back up your current instance before + upgrading. + +Update this ansible-role via ``ansible-galaxy``: + +.. code-block:: shell + + ansible-galaxy install --force openwisp.openwisp2 + +Run ``ansible-playbook`` again **from your local machine**: + +.. code-block:: shell + + ansible-playbook -i hosts playbook.yml + +You may also run the playbook automatically periodically or when a new +release of OpenWISP2, for example, by setting up a continuous integration +system. + +.. _ansible_deploying_development_version: + +Deploying the Development Version of OpenWISP +--------------------------------------------- + +The following steps will help you set up and install the development +version of OpenWISP which is not released yet, but ships new features and +improvements. + +Create a directory for organizing your playbook, roles and collections. In +this example, ``openwisp-dev`` is used. Create ``roles`` and +``collections`` directories in ``~/openwisp-dev``. + +.. code-block:: + + mkdir -p ~/openwisp-dev/roles + mkdir -p ~/openwisp-dev/collections + +Change directory to ``~/openwisp-dev/`` in terminal and create +configuration and requirement files for Ansible. + +.. code-block:: + + cd ~/openwisp-dev/ + touch ansible.cfg + touch requirements.yml + +Setup ``roles_path`` and ``collections_paths`` variables in +``ansible.cfg`` as follows: + +.. code-block:: + + [defaults] + roles_path=~/openwisp-dev/roles + collections_paths=~/openwisp-dev/collections + +Ensure your ``requirements.yml`` contains following content: + +.. code-block:: yaml + + --- + roles: + - src: https://github.com/openwisp/ansible-openwisp2.git + version: master + name: openwisp.openwisp2-dev + collections: + - name: community.general + version: ">=3.6.0" + +Install requirements from the ``requirements.yml`` as follows + +.. code-block:: + + ansible-galaxy install -r requirements.yml + +Now, create hosts file and playbook.yml: + +.. code-block:: + + touch hosts + touch playbook.yml + +Follow instructions in :ref:`ansible_create_inventory_file` section to +configure ``hosts`` file. + +You can reference the example playbook below (tested on Debian 11) for +installing a fully-featured version of OpenWISP. + +.. code-block:: yaml + + - hosts: openwisp2 + become: "{{ become | default('yes') }}" + roles: + - openwisp.openwisp2-dev + vars: + openwisp2_network_topology: true + openwisp2_firmware_upgrader: true + openwisp2_radius: true + openwisp2_monitoring: true # monitoring is enabled by default + +Read :doc:`role-variables` section to learn about available configuration +variables. + +Follow instructions in :ref:`ansible_run_playbook` section to run above +playbook. diff --git a/docs/user/role-variables.rst b/docs/user/role-variables.rst new file mode 100644 index 00000000..4a4434df --- /dev/null +++ b/docs/user/role-variables.rst @@ -0,0 +1,469 @@ +Role Variables +============== + +This role has many variables values that can be changed to best suit your +needs. + +Below are listed all the variables you can customize (you may also want to +take a look at `the default values of these variables +`__). + +.. code-block:: yaml + + - hosts: yourhost + roles: + # you can add other roles here + - openwisp.openwisp2 + vars: + # Enable the modules you want to use + openwisp2_network_topology: false + openwisp2_firmware_upgrader: false + openwisp2_monitoring: true + # you may replace the values of these variables with any value or URL + # supported by pip (the python package installer) + # use these to install forks, branches or development versions + # WARNING: only do this if you know what you are doing; disruption + # of service is very likely to occur if these variables are changed + # without careful analysis and testing + openwisp2_controller_version: "openwisp-controller~=1.0.0" + openwisp2_network_topology_version: "openwisp-network-topology~=1.0.0" + openwisp2_firmware_upgrader_version: "openwisp-firmware-upgrader~=1.0.0" + openwisp2_monitoring_version: "openwisp-monitoring~=1.0.0" + openwisp2_radius_version: "openwisp-radius~=1.0.0" + openwisp2_django_version: "django~=3.2.13" + # Setting this to true will enable subnet division feature of + # openwisp-controller. Refer openwisp-controller documentation + # for more information. https://github.com/openwisp/openwisp-controller#subnet-division-app + # By default, it is set to false. + openwisp2_controller_subnet_division: true + # when openwisp2_radius_urls is set to false, the radius module + # is setup but it's urls are not added, which means API and social + # views cannot be used, this is helpful if you have an external + # radius instance. + openwisp2_radius_urls: "{{ openwisp2_radius }}" + openwisp2_path: /opt/openwisp2 + # It is recommended that you change the value of this variable if you intend to use + # OpenWISP2 in production, as a misconfiguration may result in emails not being sent + openwisp2_default_from_email: "openwisp2@yourhostname.com" + # Email backend used by Django for sending emails. By default, the role + # uses "CeleryEmailBackend" from django-celery-email. + # (https://github.com/pmclanahan/django-celery-email) + openwisp2_email_backend: "djcelery_email.backends.CeleryEmailBackend" + # Email timeout in seconds used by Django for blocking operations + # like connection attempts. For more info read the Django documentation, + # https://docs.djangoproject.com/en/3.2/ref/settings/#email-timeout. + # Defaults to 10 seconds. + openwisp2_email_timeout: 5 + # edit database settings only if you are not using sqlite + # eg, for deploying with PostgreSQL (recommended for production usage) + # you will need the PostGIS spatial extension, find more info at: + # https://docs.djangoproject.com/en/4.1/ref/contrib/gis/tutorial/ + openwisp2_database: + engine: django.contrib.gis.db.backends.postgis + name: "{{ DB_NAME }}" + user: "{{ DB_USER }}" + host: "{{ DB_HOST }}" + password: "{{ DB_PASSWORD }}" + port: 5432 + # SPATIALITE_LIBRARY_PATH django setting + # The role will attempt determining the right mod-spatialite path automatically + # But you can use this variable to customize the path or fix future arising issues + openwisp2_spatialite_path: "mod_spatialite.so" + # customize other django settings: + openwisp2_language_code: en-gb + openwisp2_time_zone: UTC + # openwisp-controller context + openwisp2_context: {} + # additional allowed hosts + openwisp2_allowed_hosts: + - myadditionalhost.openwisp.org + # geographic map settings + openwisp2_leaflet_config: + DEFAULT_CENTER: [42.06775, 12.62011] + DEFAULT_ZOOM: 6 + # enable/disable geocoding check + openwisp2_geocoding_check: true + # specify path to a valid SSL certificate and key + # (a self-signed SSL cert will be generated if omitted) + openwisp2_ssl_cert: "/etc/nginx/ssl/server.crt" + openwisp2_ssl_key: "/etc/nginx/ssl/server.key" + # customize the self-signed SSL certificate info if needed + openwisp2_ssl_country: "US" + openwisp2_ssl_state: "California" + openwisp2_ssl_locality: "San Francisco" + openwisp2_ssl_organization: "IT dep." + # the following setting controls which ip address range + # is allowed to access the controller via unencrypted HTTP + # (this feature is disabled by default) + openwisp2_http_allowed_ip: "10.8.0.0/16" + # additional python packages that will be installed with pip + openwisp2_extra_python_packages: + - bpython + - django-owm-legacy + # additional django apps that will be added to settings.INSTALLED_APPS + # (if the app needs to be installed, the name its python package + # must be also added to the openwisp2_extra_python_packages var) + openwisp2_extra_django_apps: + - owm_legacy + # additional django settings example + openwisp2_extra_django_settings: + CSRF_COOKIE_AGE: 2620800.0 + # in case you need to add python instructions to the django settings file + openwisp2_extra_django_settings_instructions: + - TEMPLATES[0]['OPTIONS']['loaders'].insert(0, 'apptemplates.Loader') + # extra URL settings for django + openwisp2_extra_urls: + - "path(r'', include('my_custom_app.urls'))" + # allows to specify imports that are used in the websocket routes, eg: + openwisp2_websocket_extra_imports: + - from my_custom_app.websockets.routing import get_routes as get_custom_app_routes + # allows to specify extra websocket routes, eg: + openwisp2_websocket_extra_routes: + # Callable that returns a list of routes + - get_custom_app_routes() + # List of routes + - "[path('ws/custom-app/', consumer.CustomAppConsumer.as_asgi())]" + # controller URL are enabled by default + # but can be disabled in multi-VM installations if needed + openwisp2_controller_urls: true + # The default retention policy that applies to the timeseries data + # https://github.com/openwisp/openwisp-monitoring#openwisp-monitoring-default-retention-policy + openwisp2_monitoring_default_retention_policy: "26280h0m0s" # 3 years + # whether NGINX should be installed + openwisp2_nginx_install: true + # spdy protocol support (disabled by default) + openwisp2_nginx_spdy: false + # HTTP2 protocol support (disabled by default) + openwisp2_nginx_http2: false + # ipv6 must be enabled explicitly to avoid errors + openwisp2_nginx_ipv6: false + # nginx client_max_body_size setting + openwisp2_nginx_client_max_body_size: 10M + # list of upstream servers for OpenWISP + openwisp2_nginx_openwisp_server: + - "localhost:8000" + # dictionary containing more nginx settings for + # the 443 section of the openwisp2 nginx configuration + # IMPORTANT: 1. you can add more nginx settings in this dictionary + # 2. here we list the default values used + openwisp2_nginx_ssl_config: + gzip: "on" + gzip_comp_level: "6" + gzip_proxied: "any" + gzip_min_length: "1000" + gzip_types: + - "text/plain" + - "text/html" + - "image/svg+xml" + - "application/json" + - "application/javascript" + - "text/xml" + - "text/css" + - "application/xml" + - "application/x-font-ttf" + - "font/opentype" + # nginx error log configuration + openwisp2_nginx_access_log: "{{ openwisp2_path }}/log/nginx.access.log" + openwisp2_nginx_error_log: "{{ openwisp2_path }}/log/nginx.error.log error" + # nginx Content Security Policy header, customize if needed + openwisp2_nginx_csp: > + CUSTOM_NGINX_SECURITY_POLICY + # uwsgi gid, omitted by default + openwisp2_uwsgi_gid: null + # number of uWSGI process to spawn. Default value is 1. + openwisp2_uwsgi_processes: 1 + # number of threads each uWSGI process will have. Default value is 1. + openwisp2_uwsgi_threads: 2 + # value of the listen queue of uWSGI + openwisp2_uwsgi_listen: 100 + # socket on which uwsgi should listen. Defaults to UNIX socket + # at "{{ openwisp2_path }}/uwsgi.sock" + openwisp2_uwsgi_socket: 127.0.0.1:8000 + # extra uwsgi configuration parameters that cannot be + # configured using dedicated ansible variables + openwisp2_uwsgi_extra_conf: | + single-interpreter=True + log-4xx=True + log-5xx=True + disable-logging=True + auto-procname=True + # whether daphne should be installed + # must be enabled for serving websocket requests + openwisp2_daphne_install: true + # number of daphne process to spawn. Default value is 1 + openwisp2_daphne_processes: 2 + # maximum time to allow a websocket to be connected (in seconds) + openwisp2_daphne_websocket_timeout: 1800 + # the following setting controls which ip address range + # is allowed to access the openwisp2 admin web interface + # (by default any IP is allowed) + openwisp2_admin_allowed_network: null + # install ntp client (enabled by default) + openwisp2_install_ntp: true + # if you have any custom supervisor service, you can + # configure it to restart along with other supervisor services + openwisp2_extra_supervisor_restart: + - name: my_custom_service + when: my_custom_service_enabled + # Disable usage metric collection. It is enabled by default. + # Read more about it at + # https://openwisp.io/docs/user/usage-metric-collection.html + openwisp2_usage_metric_collection: false + # enable sentry example + openwisp2_sentry: + dsn: "https://7d2e3cd61acc32eca1fb2a390f7b55e1:bf82aab5ddn4422688e34a486c7426e3@getsentry.com:443/12345" + openwisp2_default_cert_validity: 1825 + openwisp2_default_ca_validity: 3650 + # the following options for redis allow to configure an external redis instance if needed + openwisp2_redis_install: true + openwisp2_redis_host: localhost + openwisp2_redis_port: 6379 + openwisp2_redis_cache_url: "redis://{{ openwisp2_redis_host }}:{{ openwisp2_redis_port }}/1" + # the following options are required to configure influxdb which is used in openwisp-monitoring + openwisp2_influxdb_install: true + openwisp2_timeseries_database: + backend: "openwisp_monitoring.db.backends.influxdb" + user: "openwisp" + password: "openwisp" + name: "openwisp2" + host: "localhost" + port: 8086 + # celery concurrency for the default queue, by default the number of CPUs is used + # celery concurrency for the default queue, by default it is set to 1 + # Setting it to "null" will make concurrency equal to number of CPUs if autoscaling is not used + openwisp2_celery_concurrency: null + # alternative to the previous option, the celery autoscale option can be set if needed + # for more info, consult the documentation of celery regarding "autoscaling" + # by default it is set to "null" (no autoscaling) + openwisp2_celery_autoscale: 4,1 + # prefetch multiplier for the default queue, + # the default value is calculated automatically by celery + openwisp2_celery_prefetch_multiplier: null + # celery queuing mode for the default queue, + # leaving the default will work for most cases + openwisp2_celery_optimization: default + # whether the dedicated celerybeat worker is enabled which is + # responsible for triggering periodic tasks + # must be turned on unless there's another server running celerybeat + openwisp2_celerybeat: true + # whether the dedicated worker for the celery "network" queue is enabled + # must be turned on unless there's another server running a worker for this queue + openwisp2_celery_network: true + # concurrency option for the "network" queue (a worker is dedicated solely to network operations) + # the default is 1. Setting it to "null" will make concurrency equal to number of CPUs if autoscaling is not used. + openwisp2_celery_network_concurrency: null + # alternative to the previous option, the celery autoscale option can be set if needed + # for more info, consult the documentation of celery regarding "autoscaling" + # by default it is set to "null" (no autoscaling) + openwisp2_celery_network_autoscale: 8,4 + # prefetch multiplier for the "network" queue, + # the default is 1, which mean no prefetching, + # because the network tasks are long running and is better + # to distribute the tasks to multiple processes + openwisp2_celery_network_prefetch_multiplier: 1 + # celery queuing mode for the "network" queue, + # fair mode is used in this case, which means + # tasks will be equally distributed among workers + openwisp2_celery_network_optimization: fair + # whether the dedicated worker for the celery "firmware_upgrader" queue is enabled + # must be turned on unless there's another server running a worker for this queue + openwisp2_celery_firmware_upgrader: true + # concurrency option for the "firmware_upgrader" queue (a worker is dedicated solely to firmware upgrade operations) + # the default is 1. Setting it to "null" will make concurrency equal to number of CPUs if autoscaling is not used + openwisp2_celery_firmware_upgrader_concurrency: null + # alternative to the previous option, the celery autoscale option can be set if needed + # for more info, consult the documentation of celery regarding "autoscaling" + # by default it is set to "null" (no autoscaling) + openwisp2_celery_firmware_upgrader_autoscale: 8,4 + # prefetch multiplier for the "firmware_upgrader" queue, + # the default is 1, which mean no prefetching, + # because the firmware upgrade tasks are long running and is better + # to distribute the tasks to multiple processes + openwisp2_celery_firmware_upgrader_prefetch_multiplier: 1 + # celery queuing mode for the "firmware_upgrader" queue, + # fair mode is used in this case, which means + # tasks will be equally distributed among workers + openwisp2_celery_firmware_upgrader_optimization: fair + # whether the dedicated worker for the celery "monitoring" queue is enabled + # must be turned on unless there's another server running a worker for this queue + openwisp2_celery_monitoring: true + # concurrency option for the "monitoring" queue (a worker is dedicated solely to monitoring operations) + # the default is 2. Setting it to "null" will make concurrency equal to number of CPUs + # if autoscaling is not used. + openwisp2_celery_monitoring_concurrency: null + # alternative to the previous option, the celery autoscale option can be set if needed + # for more info, consult the documentation of celery regarding "autoscaling" + # by default it is set to "null" (no autoscaling) + openwisp2_celery_monitoring_autoscale: 4,8 + # prefetch multiplier for the "monitoring" queue, + # the default is 1, which mean no prefetching, + # because the monitoring tasks can be long running and is better + # to distribute the tasks to multiple processes + openwisp2_celery_monitoring_prefetch_multiplier: 1 + # celery queuing mode for the "monitoring" queue, + # fair mode is used in this case, which means + # tasks will be equally distributed among workers + openwisp2_celery_monitoring_optimization: fair + # whether the default celery task routes should be written to the settings.py file + # turn this off if you're defining custom task routing rules + openwisp2_celery_task_routes_defaults: true + # celery settings + openwisp2_celery_broker_url: redis://{{ openwisp2_redis_host }}:{{ openwisp2_redis_port }}/3 + openwisp2_celery_task_acks_late: true + # maximum number of retries by celery before giving up when broker is unreachable + openwisp2_celery_broker_max_tries: 10 + # whether to activate the django logging configuration in celery + # if set to true, will log all the celery events in the same log stream used by django + # which will cause log lines to be written to "{{ openwisp2_path }}/log/openwisp2.log" + # instead of "{{ openwisp2_path }}/log/celery.log" and "{{ openwisp2_path }}/log/celerybeat.log" + openwisp2_django_celery_logging: false + # postfix is installed by default, set to false if you don't need it + openwisp2_postfix_install: true + # allow overriding default `postfix_smtp_sasl_auth_enable` variable + postfix_smtp_sasl_auth_enable_override: true + # allow overriding postfix_smtpd_relay_restrictions + postfix_smtpd_relay_restrictions_override: permit_mynetworks + # allows overriding the default duration for keeping notifications + openwisp2_notifications_delete_old_notifications: 10 + # Expiration time limit (in seconds) of magic sign-in links. + # Magic sign-in links are used only when OpenWISP RADIUS is enabled. + openwisp2_django_sesame_max_age: 1800 # 30 minutes + # Maximum file size(in bytes) allowed to be uploaded as firmware image. + # It overrides "openwisp2_nginx_client_max_body_size" setting + # and updates nginx configuration accordingly. + openwisp2_firmware_upgrader_max_file_size: 41943040 # 40MB + # to add multi-language support + openwisp2_internationalization: true + openwisp2_users_auth_api: true + # Allows setting OPENWISP_USERS_USER_PASSWORD_EXPIRATION setting. + # Read https://github.com/openwisp/openwisp-users#openwisp_users_user_password_expiration + openwisp2_users_user_password_expiration: 30 + # Allows setting OPENWISP_USERS_STAFF_USER_PASSWORD_EXPIRATION setting. + # Read https://github.com/openwisp/openwisp-users#openwisp_users_staff_user_password_expiration + openwisp2_users_staff_user_password_expiration: 30 + # used for SMS verification, the default is a dummy SMS backend + # which prints to standard output and hence does nothing + # one of the available providers from django-sendsms can be + # used or alternatively, you can write a backend class for your + # favorite SMS API gateway + openwisp2_radius_sms_backend: "sendsms.backends.console.SmsBackend" + openwisp2_radius_sms_token_max_ip_daily: 25 + openwisp2_radius_delete_old_radiusbatch_users: 365 + openwisp2_radius_cleanup_stale_radacct: 1 + openwisp2_radius_delete_old_postauth: 365 + # days for which the radius accounting sessions (radacct) are retained, + # 0 means sessions are kept forever. + # we highly suggest to set this number according + # to the privacy regulation of your jurisdiction + openwisp2_radius_delete_old_radacct: 365 + # days after which inactive users will flagged as unverified + # Read https://openwisp-radius.readthedocs.io/en/latest/user/settings.html#openwisp-radius-unverify-inactive-users + openwisp2_radius_unverify_inactive_users: 540 + # days after which inactive users will be deleted + # Read https://openwisp-radius.readthedocs.io/en/latest/user/settings.html#openwisp-radius-delete-inactive-users + openwisp2_radius_delete_inactive_users: 540 + openwisp2_radius_allowed_hosts: ["127.0.0.1"] + # allow disabling celery beat tasks if needed + openwisp2_monitoring_periodic_tasks: true + openwisp2_radius_periodic_tasks: true + openwisp2_usage_metric_collection_periodic_tasks: true + # this role provides a default configuration of freeradius + # if you manage freeradius on a different machine or you need different configurations + # you can disable this default behavior + openwisp2_freeradius_install: true + # Set an account to expire T seconds after first login. + # This variable sets the value of T. + freeradius_expire_attr_after_seconds: 86400 + freeradius_dir: /etc/freeradius/3.0 + freeradius_mods_available_dir: "{{ freeradius_dir }}/mods-available" + freeradius_mods_enabled_dir: "{{ freeradius_dir }}/mods-enabled" + freeradius_sites_available_dir: "{{ freeradius_dir }}/sites-available" + freeradius_sites_enabled_dir: "{{ freeradius_dir }}/sites-enabled" + freeradius_rest: + url: "https://{{ inventory_hostname }}/api/v1/freeradius" + freeradius_safe_characters: "+@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /" + # Sets the source path of the template that contains freeradius site configuration. + # Defaults to "templates/freeradius/openwisp_site.j2" shipped in the role. + freeradius_openwisp_site_template_src: custom_freeradius_site.j2 + # Whether to deploy the default openwisp_site for FreeRADIUS. + # Defaults to true. + freeradius_deploy_openwisp_site: false + # FreeRADIUS listen address for the openwisp_site. + # Defaults to "*", i.e. listen on all interfaces. + freeradius_openwisp_site_listen_ipaddr: "10.8.0.1" + # A list of dict that includes organization's name, UUID, RADIUS token, + # TLS configuration, and ports for authentication, accounting, and inner tunnel. + # This list of dict is used to generate FreeRADIUS sites that support + # WPA Enterprise (EAP-TTLS-PAP) authentication. + # Defaults to an empty list. + freeradius_eap_orgs: + # The name should not contain spaces or special characters + - name: openwisp + # UUID of the organization can be retrieved from the OpenWISP admin + uuid: 00000000-0000-0000-0000-000000000000 + # Radius token of the organization can be retrieved from the OpenWISP admin + radius_token: secret-radius-token + # Port used by the authentication service for this FreeRADIUS site + auth_port: 1832 + # Port used by the accounting service for this FreeRADIUS site + acct_port: 1833 + # Port used by the authentication service of inner tunnel for this FreeRADIUS site + inner_tunnel_auth_port: 18330 + # CA certificate for the FreeRADIUS site + ca: /etc/freeradius/certs/ca.crt + # TLS certificate for the FreeRADIUS site + cert: /etc/freeradius/certs/cert.pem + # TLS private key for the FreeRADIUS site + private_key: /etc/freeradius/certs/key.pem + # Diffie-Hellman key for the FreeRADIUS site + dh: /etc/freeradius/certs/dh + # Extra instructions for the "tls-config" section of the EAP module + # for the FreeRADIUS site + tls_config_extra: | + private_key_password = whatever + ecdh_curve = "prime256v1" + # Sets the source path of the template that contains freeradius site configuration + # for WPA Enterprise (EAP-TTLS-PAP) authentication. + # Defaults to "templates/freeradius/eap/openwisp_site.j2" shipped in the role. + freeradius_eap_openwisp_site_template_src: custom_eap_openwisp_site.j2 + # Sets the source path of the template that contains freeradius inner tunnel + # configuration for WPA Enterprise (EAP-TTLS-PAP) authentication. + # Defaults to "templates/freeradius/eap/inner_tunnel.j2" shipped in the role. + freeradius_eap_inner_tunnel_template_src: custom_eap_inner_tunnel.j2 + # Sets the source path of the template that contains freeradius EAP configuration + # for WPA Enterprise (EAP-TTLS-PAP) authentication. + # Defaults to "templates/freeradius/eap/eap.j2" shipped in the role. + freeradius_eap_template_src: custom_eap.j2 + cron_delete_old_notifications: "'hour': 0, 'minute': 0" + cron_deactivate_expired_users: "'hour': 0, 'minute': 5" + cron_delete_old_radiusbatch_users: "'hour': 0, 'minute': 10" + cron_cleanup_stale_radacct: "'hour': 0, 'minute': 20" + cron_delete_old_postauth: "'hour': 0, 'minute': 30" + cron_delete_old_radacct: "'hour': 1, 'minute': 30" + cron_password_expiration_email: "'hour': 1, 'minute': 0" + cron_unverify_inactive_users: "'hour': 1, 'minute': 45" + cron_delete_inactive_users: "'hour': 1, 'minute': 55" + # cross-origin resource sharing (CORS) settings + # https://pypi.org/project/django-cors-headers/ + openwisp2_django_cors: + # Setting this to "true" will install the django-cors-headers package + # and configure the Django middleware setting to support CORS. + # By default, it is set to false. + enabled: true + # Configures "CORS_ALLOWED_ORIGINS" setting of the django-cors-headers + # package. A list of origins that are authorized to make cross-site + # HTTP requests. Read https://github.com/adamchainz/django-cors-headers#cors_allowed_origins-sequencestr + # for detail. By default, it is set to an empty list. + allowed_origins_list: ["https://log.openwisp.org"] + # Configures "CORS_REPLACE_HTTPS_REFERER" setting of the django-cors-headers + # package. Read https://github.com/adamchainz/django-cors-headers#cors_replace_https_referer-bool + # for detail. Setting this to "true" will also configure the + # Django middleware setting to add "CorsPostCsrfMiddleware". + # By default, it is set to false. + replace_https_referer: true + +**Note**: The default values for settings provided to control the number +of process and threads of uWSGI and Daphne are set conservatively. It is +expected from user to update these settings to suit scale of their +project. The same thing applies for concurrency and autoscale settings for +celery workers. diff --git a/docs/user/system-requirements.rst b/docs/user/system-requirements.rst new file mode 100644 index 00000000..da20d431 --- /dev/null +++ b/docs/user/system-requirements.rst @@ -0,0 +1,48 @@ +System Requirements +=================== + +The following specifications will run a new, *empty* instance of OpenWISP. +Please ensure you account for the amount of disk space your use case will +require, e.g. allocate enough space for users to upload floor plan images. + +Hardware Requirements (Recommended) +----------------------------------- + +- 2 CPUs +- 2 GB Memory +- Disk space - depends on the projected size of your database and uploaded + photo images + +Keep in mind that increasing the number of celery workers will require +more memory and CPU. You will need to increase the amount of celery +workers as the number of devices you manage grows. + +For more information about how to increase concurrency, look for the +variables which end with ``_concurrency`` or ``_autoscale`` in the +:doc:`role-variables` section. + +Software +-------- + +Generally a fresh installation of one of the supported operating systems +is sufficient; no pre-configuration required. The Ansible Playbook will +install and configure all dependencies and leave you with a running +OpenWISP installation. + +.. important:: + + Ensure the hostname of your target machine matches what is in your + Ansible configuration file. Also, please ensure that Ansible can + access your target machine by SSH, be it either with a key or + password. For more information see the `Ansible Getting Started + Documentation + `__. + +Supported Operating Systems +--------------------------- + +- Debian 12 +- Debian 11 +- Ubuntu 24 LTS +- Ubuntu 22 LTS +- Ubuntu 20 LTS diff --git a/docs/user/troubleshooting.rst b/docs/user/troubleshooting.rst new file mode 100644 index 00000000..d2f875f9 --- /dev/null +++ b/docs/user/troubleshooting.rst @@ -0,0 +1,68 @@ +Troubleshooting +=============== + +OpenWISP is deployed using **uWSGI**, it also uses **daphne** fo +WebSockets and **celery** as task queue. + +All this services are run by **supervisor**. + +.. code-block:: shell + + sudo service supervisor start|stop|status + +You can view each individual process run by supervisor with the following +command: + +.. code-block:: shell + + sudo supervisorctl status + +For more info about Supervisord, refer to `Running supervisorctl +`__. + +The **nginx** web server sits in front of the **uWSGI** application +server. You can control nginx with the following commands: + +.. code-block:: shell + + service nginx status start|stop|status + +OpenWISP is installed in ``/opt/openwisp2`` (unless you changed the +``openwisp2_path`` variable in the ansible playbook configuration), these +are some useful directories to look for when experiencing issues. + +========================= ========================== +Location Description +========================= ========================== +/opt/openwisp2 The OpenWISP 2 root dir. +/opt/openwisp2/log Log files +/opt/openwisp2/env Python virtual env +/opt/openwisp2/db.sqlite3 OpenWISP 2 sqlite database +========================= ========================== + +All processes are running as ``www-data`` user. + +If you need to copy or edit files, you can switch to ``www-data`` user +with the following commands: + +.. code-block:: shell + + sudo su www-data -s /bin/bash + cd /opt/openwisp2 + source env/bin/activate + +SSL Certificate Gotchas +----------------------- + +When you access the admin website you will get an SSL certificate warning +because the playbook creates a self-signed (untrusted) SSL certificate. +You can get rid of the warning by installing your own trusted certificate +and set the ``openwisp2_ssl_cert`` and ``openwisp2_ssl_key`` variables +accordingly or by following the instructions explained in the section +:doc:`certbot-ssl`. + +If you keep the untrusted certificate, you will also need to disable SSL +verification on devices using :doc:`openwisp-config +` by setting ``verify_ssl`` to ``0``, +although we advice against using this kind of setup in a production +environment. diff --git a/files/generate_django_secret_key.py b/files/generate_django_secret_key.py index d468b937..6faa365e 100755 --- a/files/generate_django_secret_key.py +++ b/files/generate_django_secret_key.py @@ -1,14 +1,15 @@ #!/usr/bin/env python -""" -Pseudo-random django secret key generator -""" +"""Pseudo-random django secret key generator""" from __future__ import print_function + import random -chars = 'abcdefghijklmnopqrstuvwxyz' \ - 'ABCDEFGHIJKLMNOPQRSTUVXYZ' \ - '0123456789' \ - '#()^[]-_*%&=+/' +chars = ( + 'abcdefghijklmnopqrstuvwxyz' + 'ABCDEFGHIJKLMNOPQRSTUVXYZ' + '0123456789' + '#()^[]-_*%&=+/' +) SECRET_KEY = ''.join([random.SystemRandom().choice(chars) for i in range(50)]) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..21ea6859 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,2 @@ +[tool.docstrfmt] +extend_exclude = ["templates/**/*.py"] diff --git a/templates/load_initial_data.py b/templates/load_initial_data.py index 4894cbf7..45d41693 100644 --- a/templates/load_initial_data.py +++ b/templates/load_initial_data.py @@ -7,7 +7,9 @@ template to use the same """ import os + import django + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'openwisp2.settings') django.setup() @@ -22,13 +24,12 @@ changed = False if User.objects.filter(is_superuser=True).count() < 1: - admin = User.objects.create_superuser(username='admin', - password='admin', - email='') + admin = User.objects.create_superuser(username='admin', password='admin', email='') print('superuser created') if 'django.contrib.sites' in settings.INSTALLED_APPS: from django.contrib.sites.models import Site + site = Site.objects.first() if site and 'example.com' in [site.name, site.domain]: site.name = '{{ inventory_hostname }}' diff --git a/templates/openwisp2/__init__.py b/templates/openwisp2/__init__.py index 67014dab..493e5e2c 100644 --- a/templates/openwisp2/__init__.py +++ b/templates/openwisp2/__init__.py @@ -2,4 +2,6 @@ __all__ = ['celery_app'] __openwisp_version__ = '24.0.0a' -__openwisp_installation_method__ = '{{ openwisp2_installation_method | default("ansible-openwisp2") }}' +__openwisp_installation_method__ = ( + '{{ openwisp2_installation_method | default("ansible-openwisp2") }}' +) diff --git a/templates/openwisp2/asgi.py b/templates/openwisp2/asgi.py index e9477f95..cf450b81 100644 --- a/templates/openwisp2/asgi.py +++ b/templates/openwisp2/asgi.py @@ -4,6 +4,7 @@ """ import os + import django from channels.routing import get_default_application diff --git a/templates/openwisp2/celery.py b/templates/openwisp2/celery.py index 20e28ef5..a171e1c8 100644 --- a/templates/openwisp2/celery.py +++ b/templates/openwisp2/celery.py @@ -10,9 +10,11 @@ app.autodiscover_tasks() {% if openwisp2_django_celery_logging %} -from celery.signals import setup_logging from logging.config import dictConfig +from celery.signals import setup_logging + + @setup_logging.connect def config_loggers(*args, **kwargs): dictConfig(settings.LOGGING) diff --git a/templates/openwisp2/routing.py b/templates/openwisp2/routing.py index cc43522e..3cbd22a0 100644 --- a/templates/openwisp2/routing.py +++ b/templates/openwisp2/routing.py @@ -10,11 +10,14 @@ {% if openwisp2_controller_urls %} from openwisp_controller.routing import get_routes as get_controller_routes + routes.extend(get_controller_routes()) {% endif %} {% if openwisp2_network_topology %} -from openwisp_network_topology.routing import websocket_urlpatterns as network_topology_routes +from openwisp_network_topology.routing import \ + websocket_urlpatterns as network_topology_routes + routes.extend(network_topology_routes) {% endif %} diff --git a/templates/openwisp2/settings.py b/templates/openwisp2/settings.py index 49f336ed..7f7a314b 100644 --- a/templates/openwisp2/settings.py +++ b/templates/openwisp2/settings.py @@ -1,8 +1,9 @@ import os import sys -from celery.schedules import crontab from datetime import timedelta +from celery.schedules import crontab + TESTING = 'test' in sys.argv # Build paths inside the project like this: os.path.join(BASE_DIR, ...) diff --git a/templates/openwisp2/urls.py b/templates/openwisp2/urls.py index 1bb7a0f7..c76a57c9 100644 --- a/templates/openwisp2/urls.py +++ b/templates/openwisp2/urls.py @@ -1,14 +1,15 @@ -from django.urls import include, path, reverse_lazy from django.contrib import admin from django.contrib.staticfiles.urls import staticfiles_urlpatterns +from django.urls import include, path, reverse_lazy from django.views.generic import RedirectView + {% if openwisp2_firmware_upgrader %} # When using S3_REVERSE_PROXY feature of django-private-storage, # the storage backend reverse the "serve_private_file" URL # pattern in order to proxy the file with the correct URL. -from openwisp_firmware_upgrader.private_storage.urls import ( - urlpatterns as fw_private_storage_urls, -) +from openwisp_firmware_upgrader.private_storage.urls import \ + urlpatterns as fw_private_storage_urls + {% endif %} redirect_view = RedirectView.as_view(url=reverse_lazy('admin:index'))