Use Emacs as a Django IDE on Debian

GNU Emacs is one of the most powerful text editors that has ever been created but it is like an old dog that cannot easily learn new tricks. But here we try to tame this wild animal by adding some extra packages and making it ready to start developing Django projects.

We assume that we are running Debian 10 and have also superuser access. The same procedure would also be applicable to other GNU/Linux distributions especially Ubuntu. Also, as I prefer to install packages from the official Debian repos, instead of PyPI, then expect to install system-wide packages.

Installing prerequisites

$ sudo apt install emacs elpa-elpy python3-django python-django-doc elpa-flycheck elpa-pip-requirements elpa-gitlab-ci-mode python3-autopep8 python3-pip python3-venv black elpa-magit elpa-markdown-mode markdown elpa-web-mode jupyter-console elpa-aggressive-indent elpa-diff-hl elpa-solarized-theme
  • emacs: emacs26 version of GNU Emacs
  • elpa-elpy: a very powerful Python IDE for GNU Emacs with lots of cool features
  • python3-django: High-level Python web development framework. On Debian 10 we have the LTS version which is currently 2.2
  • python-django-doc: documentation accessible from file:///usr/share/doc/python-django-doc/html/index.html
  • elpa-flycheck: syntax checker
  • elpa-pip-requirements: syntax highlighting for PIP requirements
  • elpa-gitlab-ci-mode: Emacs mode for editing GitLab CI files
  • python3-autopep8: formats Python code to conform to PEP 8
  • python3-pip: Python package installer. PIP is not installed by default on GNU/Linux distributions
  • python3-venv: creating virtual environments
  • black: Python code formatter
  • elpa-magit: the most powerful git client ever existed.
  • elpa-markdown-mode: mode for editing Markdown-formatted text
  • markdown: we need to install it to be able to view and export markdown from within GNU Emacs
  • elpa-web-mode: major emacs mode for editing web templates, here Django Templates
  • jupyter-console: Jupyter terminal client.
  • elpa-aggressive-ident: Emacs minor mode that reindents code after every change
  • elpa-diff-hl: highlight uncommitted changes using VC
  • elpa-solarized-theme: port of Solarized theme to Emacs

Now that we have installed the necessary packages we are ready to config GNU Emacs. Add the following text to your GNU Emacs configuration file, e.g.: ~/.emacs

;; load theme
;; ===========
(load-theme 'solarized-light)
;; ------

;; yasnippet
;; ========
(require 'yasnippet)
(yas-global-mode 1)
;; --------

;; Enable global company mode
;; ==========================
(require 'company)
(add-hook 'after-init-hook 'global-company-mode)
(setq company-idle-delay 1)
(setq company-minimum-prefix-length 1)
;; ---------------------------

;; magit
;; ======
(setq magit-clone-set-remote.pushDefault t)
(global-set-key (kbd "C-x g") 'magit-status)
;; ------

;; elpy; emacs python development environment
;; ==========================================
(elpy-enable)
(setq python-shell-interpreter "jupyter"
      python-shell-interpreter-args "console --simple-prompt"
      python-shell-prompt-detect-failure-warning nil)
(add-to-list 'python-shell-completion-native-disabled-interpreters
             "jupyter")
;; --------------------------------------------

;; new line at the end of the file
;; ==================================
(setq require-final-newline t)

;; show full path of the file in the frame title
;; =============================================
(setq frame-title-format
      '("" invocation-name ": "
        (:eval
         (if buffer-file-name
             (abbreviate-file-name buffer-file-name)
           "%b"))))

;; web-mode
;; ========
(require 'web-mode)
(setq web-mode-enable-engine-detection t)
(add-to-list 'auto-mode-alist '("\.djhtml\'" . web-mode))
(add-to-list 'auto-mode-alist '("\.html?\'" . web-mode))
(defun my-web-mode-hook ()
  "Hooks for web-mode."
  (setq web-mode-markup-indent-offset 2))
(add-hook 'web-mode-hook 'my-web-mode-hook)

;; aggressive-indent-mode
;; =======================
(global-aggressive-indent-mode 1)

;; diff-hl
;; =======
(global-diff-hl-mode)

Now one of the missing items is the snippets for Django projects, for instance, in Django Templates. To write your own snippets for Django Templates, write the following command to create the necessary file:

$ mkdir -p ~/.emacs.d/snippets/web-mode/django && touch ~/.emacs.d/snippets/web-mode/django/if

and then add the following text to the just created empty file:

# -- mode: snippet --
# name: if statement
# key: if
# --
{% if ${1:condition} %}
  ${2:statement}
{% endif %}
$0

By now, we have created our first snippet using Yasnippet. Using web-mode we need to set the template-engine to django for the correct syntax highlighting. To do it, run the following command in GNU Emacs, when you open an html file which contains Django Template.

M-x web-mode-set-engine

and then choose django. Alternatively you can also add the following text to the top of your html file for the automatic recognition by web-mode (which you get a not-safe warning in GNU Emacs and therefore not preferred)

<!-- -*- engine:django -*--->

And if you only use html in your Django projects, instead of using the above mentioned commands, associate all html files as Django Templates, by adding the following command to your Emacs config file

(setq web-mode-engines-alist
      '(("django" . "\\.html\\'")))

Now, you can enjoy developing your next Django project using GNU Emacs.

Install Gitea on Nginx and Secure it with Let’s Encrypt

Gitea is a free-software clone of Github, which is lightweight and released under MIT license.

I assume you are running Debian 9 and have already installed nginx.

0. Connect to the server using ssh

0.1 $ ssh myusername@ip.address.of.server

1. Create the gitea user account.

To have a clean directory, we create a separate gitea user account.

1.1 $ sudo adduser --disabled-login gitea #it is advised to disable direct login, because we do not need it.
1.2 $ sudo --login --user gitea
1.3 $ cd /home/gitea

2. Download and run gitea

Download the latest release of Gitea, from this address, https://dl.gitea.io/gitea/, it is 1.6 at the time of writing.

2.1 $ wget -O gitea https://dl.gitea.io/gitea/1.6/gitea-1.6-linux-amd64
2.2 $ chmod +x gitea #give execution permission
2.3 $ ./gitea web

3. Install and use MariaDB

3.1 $ sudo apt install mariadb-server
3.2 $ sudo mariadb
Now, create a database using the following commands, replace localhost and your-password-here.

MariaDB [(none)]> CREATE DATABASE `gitea` DEFAULT CHARACTER SET `utf8mb4` COLLATE `utf8mb4_general_ci`;
MariaDB [(none)]> CREATE USER `giteauser`@'localhost' IDENTIFIED BY 'your-password-here';
MariaDB [(none)]> GRANT ALL PRIVILEGES ON `gitea`.* TO `giteauser`@`localhost`;
MariaDB [(none)]> \q

4. Install and setup Let’s Encrypt

I assume here that the domain is git.smoha.org

4.1 $ sudo apt install certbot python-certbot-nginx
4.2 $ sudo service nginx stop #be careful, we stop the server here.
4.3 $ sudo certbot certonly --standalone -d git.smoha.org
4.4 $ sudo service nginx start

5. Setup a subdomain with Nginx

5.1 $ sudo nano /etc/nginx/sites-available/git.smoha.org

server {  
    listen 443 ssl;
    server_name git.smoha.org;
    ssl_certificate /etc/letsencrypt/live/git.smoha.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/git.smoha.org/privkey.pem;

    location / {
        proxy_set_header  X-Real-IP  $remote_addr;
        proxy_pass http://localhost:3000;
    }
}

# Redirect HTTP requests to HTTPS
server {  
    listen 80;
    server_name git.smoha.org;
    return 301 https://$host$request_uri;
}

5.2 $ sudo ln -s /etc/nginx/sites-available/git.smoha.org /etc/nginx/sites-enabled/
5.3 $ sudo service nginx restart

6. Install git

6.1 $ sudo apt install git

7. Run gitea and follow the setup

7.1 $ nohup ./gitea web
7.2 visit, https://git.smoha.org/install

Build Emacs on Debian 9

# install git
$ sudo apt install git

# install build dependencies of emacs 25 (the current version in Debian repo)
$ sudo apt build-dep emacs25

# clone the master branch of repo (current bleeding-edge version is 25)
# download size approx. 235 MiB
$ git clone -b master git://git.sv.gnu.org/emacs.git

# or alternatively, you can download the current stable release of emacs
# download size approx. 55 MiB
# Switzerland mirror
http://mirror.switch.ch/ftp/mirror/gnu/emacs/
# change directory
$ cd emacs

# generate configure script
$ ./autogen.sh all

# configure your build
$ ./configure --with-mailutils

# build emacs
$ make

# run emacs (the binary file is in src/emacs directory)
$ src/emacs

# (optional) move the binary files to the system directory to be available globally
$ sudo make install

# (optional) uninstall the newly installed emacs
# change to the emacs source directory
$ cd emacs
$ sudo make uninstall

Fix Font Rendering in Debian

The default font rendering in Debian 8 or Debian 9 sucks. To solve it you can copy the content below,
<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
 <match target="font">
  <edit mode="assign" name="rgba">
   <const>rgb</const>
  </edit>
 </match>
 <match target="font">
  <edit mode="assign" name="hinting">
   <bool>true</bool>
  </edit>
 </match>
 <match target="font">
  <edit mode="assign" name="hintstyle">
   <const>hintslight</const>
  </edit>
 </match>
 <match target="font">
  <edit mode="assign" name="antialias">
   <bool>true</bool>
  </edit>
 </match>
  <match target="font">
    <edit mode="assign" name="lcdfilter">
      <const>lcddefault</const>
    </edit>
  </match>
</fontconfig>
to the following file:
.config/fontconfig/fonts.conf
Or alternatively, you can use the following command to do the aforementioned task automatically. Do not blindly trust the files you find on the Internet. After checking my git repo here, run the following command in terminal.
$ bash <(curl -s https://framagit.org/salman/fix-font-rendering/raw/master/fix-font-rendering.sh)

Change Default Media Folder in WordPress to Download Repository on Tuxfamily

  1. Install wordpress
  2. Install WP Original Media Path plugin on WordPress
  3. Create a directory in download repository, <your-sub-dir>
  4. Go to Settings > WP Original Media Path
    1. check Activate that if you are aware of what you are doing.
    2. Change Store uploads in this folder to /data/repository/<your-project>/<your-sub-dir>
    3. Change Full URL path to files to https://download.tuxfamily.org/<your-project>/<your-sub-dir>

Example:

My project on Tuxfamily is called smohaorg and I created a subdirectory in download section which is named wordpressmedia, so I have to use the following:
  • /data/repository/smohaorg/wordpressmedia
  • https://download.tuxfamily.org/smohaorg/wordpressmedia