diff --git a/playbooks/link.yml b/playbooks/link.yml index c99a703..6e2a328 100644 --- a/playbooks/link.yml +++ b/playbooks/link.yml @@ -1,5 +1,5 @@ --- -- name: Podman CDR Link | Deploy and update CDR Link instances +- name: CDR Link | Deploy and update CDR Link instances hosts: - cdr_link roles: diff --git a/playbooks/seafile.yml b/playbooks/seafile.yml deleted file mode 100644 index cf17ee0..0000000 --- a/playbooks/seafile.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -- name: Podman Seafile | Deploy and update Seafile instances - hosts: - - seafile - roles: - - role: sr2c.core.baseline - tags: bootstrap - - role: sr2c.apps.podman_seafile - tags: seafile diff --git a/roles/podman_link/templates/home/nginx.conf b/roles/podman_link/templates/home/nginx.conf index 4f32515..594d187 100644 --- a/roles/podman_link/templates/home/nginx.conf +++ b/roles/podman_link/templates/home/nginx.conf @@ -1,28 +1,48 @@ -# {{ ansible_managed }} - resolver 10.89.0.1 ipv6=off valid=10s; +# If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the +# scheme used to connect to this server +map $http_x_forwarded_proto $proxy_x_forwarded_proto { + default $http_x_forwarded_proto; + '' $scheme; +} +# If we receive X-Forwarded-Port, pass it through; otherwise, pass along the +# server port the client connected to +map $http_x_forwarded_port $proxy_x_forwarded_port { + default $http_x_forwarded_port; + '' $server_port; +} # If we receive Upgrade, set Connection to "upgrade"; otherwise, delete any # Connection header that may have been passed to this server map $http_upgrade $proxy_connection { default upgrade; '' close; } - # Apply fix for very long server names server_names_hash_bucket_size 128; - +# Default dhparam +# Set appropriate X-Forwarded-Ssl header +map $scheme $proxy_x_forwarded_ssl { + default off; + https on; +} gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; - +log_format vhost '$host $remote_addr - $remote_user [$time_local] ' + '"$request" $status $body_bytes_sent ' + '"$http_referer" "$http_user_agent"'; +access_log off; # HTTP 1.1 support proxy_http_version 1.1; - proxy_buffering off; proxy_set_header Host $http_host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $proxy_connection; - -# Mitigate httpoxy attack +proxy_set_header X-Real-IP $remote_addr; +proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto; +proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl; +proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port; +# Mitigate httpoxy attack (see README for details) proxy_set_header Proxy ""; server { @@ -46,6 +66,13 @@ upstream zammad { server zammad-nginx:8080 resolve; } +server { + server_name {{ podman_link_web_hostname }}; + listen 80 ; + access_log /var/log/nginx/access.log vhost; + return 301 https://$host$request_uri; +} + server { server_name {{ podman_link_web_hostname }}; listen 443 ssl; @@ -56,16 +83,12 @@ server { ssl_certificate /etc/letsencrypt/live/{{ podman_link_web_hostname }}/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/{{ podman_link_web_hostname }}/privkey.pem; + add_header Strict-Transport-Security "max-age=31536000" always; - add_header Referrer-Policy origin always; # make sure outgoing links don't show the URL to the Matomo instance + add_header Referrer-Policy origin always; # make sure outgoing links don't show the URL to the Matomo instance add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; - location / { proxy_pass http://zammad; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $remote_addr; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Port 443; } -} +} \ No newline at end of file diff --git a/roles/podman_seafile/defaults/main.yml b/roles/podman_seafile/defaults/main.yml deleted file mode 100644 index 42d1a51..0000000 --- a/roles/podman_seafile/defaults/main.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -podman_seafile_podman_rootless_user: seafile -# podman_seafile_redis_password: \ No newline at end of file diff --git a/roles/podman_seafile/handlers/main.yml b/roles/podman_seafile/handlers/main.yml deleted file mode 100644 index b90e6b3..0000000 --- a/roles/podman_seafile/handlers/main.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -- name: Restart Seafile - ansible.builtin.systemd_service: - name: seafile.service - state: restarted - scope: user - daemon_reload: true - become: true - become_user: "{{ podman_seafile_podman_rootless_user }}" diff --git a/roles/podman_seafile/tasks/main.yml b/roles/podman_seafile/tasks/main.yml deleted file mode 100644 index 70e7518..0000000 --- a/roles/podman_seafile/tasks/main.yml +++ /dev/null @@ -1,122 +0,0 @@ ---- -- name: Podman Seafile | PATCH | Install data plate - ansible.builtin.template: - src: etc/motd.d/10-data-plate.txt - dest: /etc/motd.d/10-data-plate.txt - owner: root - group: root - mode: "0444" - become: true - -- name: Podman Seafile | PATCH | Install podman and verify rootless podman user - ansible.builtin.include_role: - role: sr2c.core.podman_host - vars: - podman_host_minimum_unpriv_port: 80 - podman_host_rootless_users: ["{{ podman_seafile_podman_rootless_user }}"] - -- name: Podman Seafile | AUDIT | Get subuid range for user - ansible.builtin.command: - cmd: "getsubids {{ podman_seafile_podman_rootless_user }}" - register: _podman_seafile_user_subuid - changed_when: false - -- name: Podman Seafile | AUDIT | Get subgid range for user - ansible.builtin.command: - cmd: "getsubids -g {{ podman_seafile_podman_rootless_user }}" - register: _podman_seafile_user_subgid - changed_when: false - -- name: Podman Seafile | AUDIT | Parse outputs of getsubids and store results - ansible.builtin.set_fact: - _podman_seafile_user_subuid_start: "{{ (_podman_seafile_user_subuid.stdout_lines[0].split()[2] | int) }}" - _podman_seafile_user_subgid_start: "{{ (_podman_seafile_user_subgid.stdout_lines[0].split()[2] | int) }}" - -# MySQL runs with UID/GID 999 inside the container -- name: Podman Seafile | PATCH | Create data directory for MySQL - ansible.builtin.file: - path: "/home/{{ podman_seafile_podman_rootless_user }}/mysql_data" - owner: "{{ _podman_seafile_user_subuid_start + 998 }}" - group: "{{ _podman_seafile_user_subgid_start + 998 }}" - mode: "0750" - state: "directory" - become: true - -# Seafile runs as root inside the container -- name: Podman Seafile | PATCH | Create data directories for Seafile - ansible.builtin.file: - path: "/home/{{ podman_seafile_podman_rootless_user }}/{{ item }}" - owner: "{{ podman_seafile_podman_rootless_user }}" - group: "{{ podman_seafile_podman_rootless_user }}" - mode: "0755" - state: "directory" - become: true - with_items: - - seafile_data - - seadoc_data - - onlyoffice/logs - - onlyoffice/data - - onlyoffice/lib - -- name: Podman CDR Link | PATCH | Install container quadlets - ansible.builtin.template: - src: "home/podman/config/containers/systemd/{{ item }}" - dest: "/home/{{ podman_seafile_podman_rootless_user }}/.config/containers/systemd/{{ item }}" - owner: "{{ podman_seafile_podman_rootless_user }}" - mode: "0400" - with_items: - - mysql.container - - redis.container - - seafile.container - - seadoc.container - - onlyoffice.container - - frontend.network - - seafile.network - become: true - notify: - - Restart Seafile - -- name: Podman Seafile | PATCH | Set up nginx and Let's Encrypt certificate - ansible.builtin.include_role: - name: sr2c.core.podman_nginx - vars: - podman_nginx_frontend_network: frontend - podman_nginx_podman_rootless_user: "{{ podman_seafile_podman_rootless_user }}" - podman_nginx_primary_hostname: "{{ podman_seafile_hostname }}" - -- name: Podman Seafile | PATCH | Install production nginx configuration file - ansible.builtin.template: - src: home/podman/nginx/nginx.conf - dest: "/home/{{ podman_seafile_podman_rootless_user }}/nginx/nginx.conf" - owner: "{{ podman_seafile_podman_rootless_user }}" - group: "{{ podman_seafile_podman_rootless_user }}" - mode: "0644" - become: true - notify: - - Restart nginx - -- name: Podman Seafile | PATCH | Ensure services are running and enabled - ansible.builtin.systemd_service: - name: seafile.service - scope: user - masked: false - state: started - enabled: true - become: true - become_user: "{{ podman_seafile_podman_rootless_user }}" - -- name: Podman Seafile | AUDIT | Wait until the seahub config file is created - ansible.builtin.wait_for: - path: "/home/{{ podman_seafile_podman_rootless_user }}/seafile_data/seafile/conf/seahub_settings.py" - state: present - become: true - -- name: Podman Seafile | PATCH | Append Seafile config block from template for proxy and OAuth - ansible.builtin.blockinfile: - path: "/home/{{ podman_seafile_podman_rootless_user }}/seafile_data/seafile/conf/seahub_settings.py" - block: "{{ lookup('ansible.builtin.template', 'home/podman/seafile_data/seahub_settings.py') }}" - insertafter: EOF - marker: "# {mark} ANSIBLE MANAGED BLOCK (Keycloak OAuth login)" - become: true - notify: - - Restart Seafile diff --git a/roles/podman_seafile/templates/etc/motd.d/10-data-plate.txt b/roles/podman_seafile/templates/etc/motd.d/10-data-plate.txt deleted file mode 100644 index 096b7a8..0000000 --- a/roles/podman_seafile/templates/etc/motd.d/10-data-plate.txt +++ /dev/null @@ -1,8 +0,0 @@ - ========================================================= - A Seafile instance is hosted on this server. - Podman user: {{ podman_seafile_podman_rootless_user }} - ========================================================= - # Become the podman user - sudo -iu {{ podman_seafile_podman_rootless_user }} - ========================================================= - diff --git a/roles/podman_seafile/templates/home/podman/config/containers/systemd/frontend.network b/roles/podman_seafile/templates/home/podman/config/containers/systemd/frontend.network deleted file mode 100644 index 379c059..0000000 --- a/roles/podman_seafile/templates/home/podman/config/containers/systemd/frontend.network +++ /dev/null @@ -1,2 +0,0 @@ -[Network] -NetworkName=frontend diff --git a/roles/podman_seafile/templates/home/podman/config/containers/systemd/mysql.container b/roles/podman_seafile/templates/home/podman/config/containers/systemd/mysql.container deleted file mode 100644 index 47eccd8..0000000 --- a/roles/podman_seafile/templates/home/podman/config/containers/systemd/mysql.container +++ /dev/null @@ -1,16 +0,0 @@ -[Container] -ContainerName=mysql -Environment=MYSQL_ROOT_PASSWORD={{ podman_seafile_mysql_root_password | replace("%", "%%") }} -Environment=MYSQL_LOG_CONSOLE=true -Environment=MARIADB_AUTO_UPGRADE=1 -HealthCmd=["/usr/local/bin/healthcheck.sh","--connect","--mariadbupgrade","--innodb_initialized"] -HealthInterval=20s -HealthRetries=10 -HealthStartPeriod=30s -HealthTimeout=5s -Image=docker.io/mariadb:10.11 -Network=seafile.network -Volume=/home/{{ podman_seafile_podman_rootless_user }}/mysql_data:/var/lib/mysql:rw,Z - -[Service] -Restart=always diff --git a/roles/podman_seafile/templates/home/podman/config/containers/systemd/onlyoffice.container b/roles/podman_seafile/templates/home/podman/config/containers/systemd/onlyoffice.container deleted file mode 100644 index c06285a..0000000 --- a/roles/podman_seafile/templates/home/podman/config/containers/systemd/onlyoffice.container +++ /dev/null @@ -1,12 +0,0 @@ -[Container] -ContainerName=onlyoffice -Environment=JWT_ENABLED=true -Environment=JWT_SECRET={{ podman_seafile_jwt_private_key | replace("%", "%%") }} -Image=docker.io/onlyoffice/documentserver:8.1.0.1 -Network=frontend.network -Volume=/home/{{ podman_seafile_podman_rootless_user }}/onlyoffice/logs:/var/log/onlyoffice:rw,Z -Volume=/home/{{ podman_seafile_podman_rootless_user }}/onlyoffice/data:/var/www/onlyoffice/Data:rw,Z -Volume=/home/{{ podman_seafile_podman_rootless_user }}/onlyoffice/lib:/var/lib/onlyoffice:rw,Z - -[Service] -Restart=always diff --git a/roles/podman_seafile/templates/home/podman/config/containers/systemd/redis.container b/roles/podman_seafile/templates/home/podman/config/containers/systemd/redis.container deleted file mode 100644 index de1d649..0000000 --- a/roles/podman_seafile/templates/home/podman/config/containers/systemd/redis.container +++ /dev/null @@ -1,9 +0,0 @@ -[Container] -ContainerName=redis -Environment=REDIS_PASSWORD={{ podman_seafile_redis_password | replace("%", "%%") }} -Exec=/bin/sh -c 'redis-server --requirepass "$$REDIS_PASSWORD"' -Image=docker.io/redis -Network=seafile.network - -[Service] -Restart=always diff --git a/roles/podman_seafile/templates/home/podman/config/containers/systemd/seadoc.container b/roles/podman_seafile/templates/home/podman/config/containers/systemd/seadoc.container deleted file mode 100644 index 9dd55f7..0000000 --- a/roles/podman_seafile/templates/home/podman/config/containers/systemd/seadoc.container +++ /dev/null @@ -1,22 +0,0 @@ -[Unit] -Requires=mysql.service -After=mysql.service - -[Container] -ContainerName=seadoc -Environment=DB_HOST=mysql -Environment=DB_PORT=3306 -Environment=DB_USER=seafile -Environment=DB_PASSWORD={{ podman_seafile_mysql_user_password | replace("%", "%%") }} -Environment=DB_NAME=seahub_db -Environment=TIME_ZONE=Etc/UTC -Environment=JWT_PRIVATE_KEY={{ podman_seafile_jwt_private_key | replace("%", "%%") }} -Environment=NON_ROOT=false -Environment=SEAHUB_SERVICE_URL=http://seafile:80 -Image=docker.io/seafileltd/sdoc-server:2.0-latest -Network=seafile.network -Network=frontend.network -Volume=/home/{{ podman_seafile_podman_rootless_user }}/seadoc_data:/shared:rw,Z - -[Service] -Restart=always diff --git a/roles/podman_seafile/templates/home/podman/config/containers/systemd/seafile.container b/roles/podman_seafile/templates/home/podman/config/containers/systemd/seafile.container deleted file mode 100644 index 335da64..0000000 --- a/roles/podman_seafile/templates/home/podman/config/containers/systemd/seafile.container +++ /dev/null @@ -1,41 +0,0 @@ -[Unit] -Requires=mysql.service redis.service -After=mysql.service redis.service - -[Container] -ContainerName=seafile -Environment=SEAFILE_MYSQL_DB_HOST=mysql -Environment=SEAFILE_MYSQL_DB_PORT=3306 -Environment=SEAFILE_MYSQL_DB_USER=seafile -Environment=SEAFILE_MYSQL_DB_PASSWORD={{ podman_seafile_mysql_user_password | replace("%", "%%") }} -Environment=INIT_SEAFILE_MYSQL_ROOT_PASSWORD={{ podman_seafile_mysql_root_password | replace("%", "%%") }} -Environment=SEAFILE_MYSQL_DB_CCNET_DB_NAME=ccnet_db -Environment=SEAFILE_MYSQL_DB_SEAFILE_DB_NAME=seafile_db -Environment=SEAFILE_MYSQL_DB_SEAHUB_DB_NAME=seahub_db -Environment=TIME_ZONE=Etc/UTC -Environment=INIT_SEAFILE_ADMIN_EMAIL={{ podman_seafile_admin_email | replace("%", "%%") }} -Environment=INIT_SEAFILE_ADMIN_PASSWORD={{ podman_seafile_admin_password | replace("%", "%%") }} -Environment=SEAFILE_SERVER_HOSTNAME={{ podman_seafile_hostname | replace("%", "%%") }} -Environment=SEAFILE_SERVER_PROTOCOL=https -Environment=SITE_ROOT=/ -Environment=NON_ROOT=false -Environment=JWT_PRIVATE_KEY={{ podman_seafile_jwt_private_key | replace("%", "%%") }} -Environment=SEAFILE_LOG_TO_STDOUT=true -Environment=CACHE_PROVIDER=redis -Environment=REDIS_HOST=redis -Environment=REDIS_PORT=6379 -Environment=REDIS_PASSWORD={{ podman_seafile_redis_password | replace("%", "%%") }} -Environment=MEMCACHED_HOST=memcached -Environment=MEMCACHED_PORT=11211 -Environment=ENABLE_NOTIFICATION_SERVER=false -Environment=ENABLE_SEAFILE_AI=false -Environment=MD_FILE_COUNT_LIMIT=100000 -Environment=ENABLE_SEADOC=true -Environment=SEADOC_SERVER_URL=https://{{ podman_seafile_hostname | replace("%", "%%") }}/sdoc-server -Image=docker.io/seafileltd/seafile-mc:13.0-latest -Network=seafile.network -Network=frontend.network -Volume=/home/{{ podman_seafile_podman_rootless_user }}/seafile_data:/shared:rw,Z - -[Service] -Restart=always diff --git a/roles/podman_seafile/templates/home/podman/config/containers/systemd/seafile.network b/roles/podman_seafile/templates/home/podman/config/containers/systemd/seafile.network deleted file mode 100644 index ded2b80..0000000 --- a/roles/podman_seafile/templates/home/podman/config/containers/systemd/seafile.network +++ /dev/null @@ -1,2 +0,0 @@ -[Network] -NetworkName=seafile diff --git a/roles/podman_seafile/templates/home/podman/nginx/nginx.conf b/roles/podman_seafile/templates/home/podman/nginx/nginx.conf deleted file mode 100644 index de05bbb..0000000 --- a/roles/podman_seafile/templates/home/podman/nginx/nginx.conf +++ /dev/null @@ -1,124 +0,0 @@ -# {{ ansible_managed }} - -error_log /dev/stdout info; -access_log /dev/stdout; - -resolver 10.89.0.1 ipv6=off valid=10s; - -gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; - -# Mitigate httpoxy attack -proxy_set_header Proxy ""; - -server { - listen 80; - listen [::]:80; - - server_name {{ podman_seafile_hostname }}; - server_tokens off; - - location /.well-known/acme-challenge/ { - root /var/www/certbot; - } - - location / { - return 301 https://{{ podman_seafile_hostname }}$request_uri; - } -} - -upstream seafile { - zone seafile_upstream 64k; - server seafile:80 resolve; -} - -upstream seadoc { - zone seadoc_upstream 64k; - server seadoc:80 resolve; -} - -upstream onlyoffice { - zone onlyoffice_upstream 64k; - server onlyoffice:80 resolve; -} - -map $http_upgrade $proxy_connection { - default upgrade; - "" close; -} - -server { - server_name {{ podman_seafile_hostname }}; - listen 443 ssl; - listen [::]:443 ssl; - http2 on; - server_tokens off; - - ssl_certificate /etc/letsencrypt/live/{{ podman_seafile_hostname }}/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/{{ podman_seafile_hostname }}/privkey.pem; - - add_header Strict-Transport-Security "max-age=31536000" always; - add_header Referrer-Policy origin always; # make sure outgoing links don't show the URL to the instance - add_header X-Content-Type-Options "nosniff" always; - add_header X-XSS-Protection "1; mode=block" always; - - location ~ ^(/accounts/login)(.*)$ { - return 301 /oauth/login$2; - } - - location / { - proxy_pass http://seafile; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $remote_addr; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Port 443; - proxy_buffering on; - proxy_buffer_size 8k; - proxy_buffers 2048 8k; - - client_max_body_size 100m; - } - - location /sdoc-server/ { - proxy_pass http://seadoc/; - proxy_redirect off; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Host $server_name; - - client_max_body_size 100m; - } - - location /socket.io { - proxy_pass http://seadoc; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection 'upgrade'; - proxy_redirect off; - - proxy_buffers 8 32k; - proxy_buffer_size 64k; - - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $http_host; - proxy_set_header X-NginX-Proxy true; - } - - location /onlyofficeds/ { - proxy_pass http://onlyoffice/; - proxy_http_version 1.1; - - client_max_body_size 100M; - - proxy_read_timeout 3600s; - proxy_connect_timeout 3600s; - - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $proxy_connection; - proxy_set_header X-Forwarded-Host $host/onlyofficeds; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } - -} diff --git a/roles/podman_seafile/templates/home/podman/seafile_data/seahub_settings.py b/roles/podman_seafile/templates/home/podman/seafile_data/seahub_settings.py deleted file mode 100644 index e6557af..0000000 --- a/roles/podman_seafile/templates/home/podman/seafile_data/seahub_settings.py +++ /dev/null @@ -1,32 +0,0 @@ -SEAFILE_SERVER_HOSTNAME = "{{ podman_seafile_hostname }}" -SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') -CSRF_TRUSTED_ORIGINS = ["https://{{ podman_seafile_hostname }}"] -FORCE_HTTPS_IN_CONF = True -USE_X_FORWARDED_HOST = True - -ENABLE_OAUTH = True - -OAUTH_CREATE_UNKNOWN_USER = True -OAUTH_ACTIVATE_USER_AFTER_CREATION = True - -OAUTH_CLIENT_ID = "{{ podman_seafile_keycloak_client_id }}" -OAUTH_CLIENT_SECRET = "{{ podman_seafile_keycloak_client_secret }}" -OAUTH_REDIRECT_URL = "https://{{ podman_seafile_hostname }}/oauth/callback/" - -OAUTH_PROVIDER_DOMAIN = '{{ podman_seafile_hostname }}' -OAUTH_AUTHORIZATION_URL = 'https://{{ podman_seafile_keycloak_hostname }}/realms/{{ podman_seafile_keycloak_realm }}/protocol/openid-connect/auth' -OAUTH_TOKEN_URL = 'https://{{ podman_seafile_keycloak_hostname }}/realms/{{ podman_seafile_keycloak_realm }}/protocol/openid-connect/token' -OAUTH_USER_INFO_URL = 'https://{{ podman_seafile_keycloak_hostname }}/realms/{{ podman_seafile_keycloak_realm }}/protocol/openid-connect/userinfo' -OAUTH_SCOPE = ["openid", "profile", "email"] -OAUTH_ATTRIBUTE_MAP = { - "sub": (True, "uid"), - "email": (False, "contact_email"), - "name": (False, "name") -} - -ENABLE_ONLYOFFICE = True -ONLYOFFICE_APIJS_URL = 'https://{{ podman_seafile_hostname }}/onlyofficeds/web-apps/apps/api/documents/api.js' -ONLYOFFICE_JWT_SECRET = '{{ podman_seafile_jwt_private_key }}' -ONLYOFFICE_FILE_EXTENSION = ('doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx', 'odt', 'fodt', 'odp', 'fodp', 'ods', 'fods', 'ppsx', 'pps', 'csv') -ONLYOFFICE_EDIT_FILE_EXTENSION = ('docx', 'pptx', 'xlsx', 'csv') -OFFICE_PREVIEW_MAX_SIZE = 30 * 1024 * 1024 # preview size, 30 MB