LUKS encrypted image with udisk

September 10, 2017 Leave a comment

I tried to find a way to create and mount a LUKS encrypted image. Thanks to udisks it starts well:

dd if=/dev/zero of=.encrypted bs=20M count=1024
/sbin/cryptsetup luksFormat .encrypted
udisksctl loop-setup -f .encrypted
udisksctl unlock -b /dev/loop0

Sadly I did not find how to Ext4 format without sudo.

sudo /sbin/mkfs.ext4 -m 0 /dev/dm-0
udisksctl mount -b /dev/dm-0

Fortunately once created it’s possible to mount the encrypted image without root privileges:

udisksctl loop-setup -f .encrypted
udisksctl unlock -b /dev/loop0
udisksctl mount -b /dev/dm-0

Removing Debian packages which are upgradable and autoremovable

September 10, 2017 Leave a comment

Keeping autoremovable packages is not very useful yet I tend to that because I always say my self “may be you’ll need it a day when you’ll have no network to reinstall it”. But upgrading autoremovable packages is even more useless. Here is how I remove them before running apt-get dist-upgrade.

sudo apt-get remove --purge $(comm -12 \
<(apt-get --dry-run dist-upgrade | grep -Po '^Inst \K[^ ]+' | sort) \
<(apt-get --dry-run autoremove | grep -Po '^Remv \K[^ ]+' | sort))
Tags: ,

Gzip files in a git history

July 3, 2017 Leave a comment

I’m migrating git repositories with large files to LFS. LFS does not support local compression and my app does support gzip compressed files so I guess its better to compress files. Thus I wrote a git filter-branch --index-filter script which gzip files in all commits. I use a pickle file to do not recompress already compressed files. It compress a 4GiB repository (.git size) of 200 commits in 2.5 hours which is not that good. I guess running faster would require hacking BFG Repo-Cleaner or use pigz instead of the Python zlib module.

from subprocess import *
import os
import tempfile
import gzip
import pickle
import shutil

def should_compress(name):
    # To be adapted to you needs
    return name.endswith('.app')

def git(*args):
    res = call(['git'] + list(args))
    assert res == 0

# Map uncompressed file SHA1 to compressed file SHA1
db_file = os.path.join(os.environ["GIT_DIR"], "gzip_rewrite.pickle")
    with open(db_file) as f:
        gzipdb = pickle.load(f)
except IOError:
    gzipdb = {}

commit = os.environ['GIT_COMMIT']

# Iterate of all files in the current commit
for l in check_output(['git', 'ls-tree', '-r', commit]).splitlines():
    f_mod, f_type, f_sha1, f_name = l.split()
    if should_compress(f_name):
        if f_sha1 not in gzipdb:
            p_show = Popen(['git', 'show', commit+':'+f_name], stdout=PIPE)
            p_hash = Popen(['git', 'hash-object', '-w', '--stdin'], stdin=PIPE, stdout=PIPE)
            print 'Compressing', f_name
            shutil.copyfileobj(p_show.stdout, gzip.GzipFile(fileobj=p_hash.stdin), 2**20)
            out, err = p_hash.communicate()
            assert out is not None
            gzipdb[f_sha1] = out
        git('update-index', '--add', '--cacheinfo', f_mod, gzipdb[f_sha1], f_name+'.gz')
        git('update-index', '--remove', f_name)

with open(db_file, "w") as f:
    pickle.dump(gzipdb, f, -1)

Shrinking pg_xlog in a Gitlab container

May 28, 2017 Leave a comment

I’m running a Gitlab container and my disk is getting full because of the Postgres pg_xlog directory. This seem to be a common problem and this blog provide a solution. Here is it with trivial adjustments to the Gitlab container context. This first require to stop Gitlab:

docker exec -it gitlab_web_1 gitlab-ctl stop
docker exec -it gitlab_web_1 /opt/gitlab/embedded/bin/pg_controldata /var/opt/gitlab/postgresql/data/ |grep Next.ID

Note the checkpoint IDs which are needed for the next command:

Latest checkpoint's NextXID:          0:86136
Latest checkpoint's NextOID:          19342

Then run the actual shrink and restart Gitlab:

docker exec -it gitlab_web_1 -u gitlab-psql /opt/gitlab/embedded/bin/pg_resetxlog -o 19342 -x 86132 -f /var/opt/gitlab/postgresql/data/
docker exec -it gitlab_web_1 gitlab-ctl start
Tags: ,

Docker container of host OS without image

March 12, 2017 Leave a comment

I often need to check that my applications binary distribution embed all its shared libraries so it can work on all distros. I used to do this with chroot and mount --bind but it’s much easier with Docker:

tar cT /dev/null | docker import - empty
docker run -v /lib:/lib:ro -v /path/to/my/app:/opt/app -it empty /opt/app/bin/app

This create an empty Docker image then run a container with only /lib mounted from the host.


GTK 3 Adwaita tabs are too high

December 18, 2016 Leave a comment

xfce4-terminal is now using GTK 3 in Debian Stretch which gives me tabs looking like:

I thinks this is too high for my 768 pixels laptop screen. Fortunately Gtk 3 themes are CSS based and can be easily tweaked. Adding:

notebook tab {
    padding: 0px;
    font-weight: normal;

to the ~/.config/gtk-3.0/gtk.css file will change all GtkNodebook widgets so they look like:

An easy way to test more CSS rules is using GtkInspector.

This is fixed in xfce4-terminal 0.8.4:


Mantis to Gitlab converter

October 2, 2016 Leave a comment

Still migrating my old mantis/tiki/gitweb forge to Gitlab. Below is the script I used to migrate my Mantis server to Gitlab. It use the Mantis WSDL API with Zeep and python-gitlab which make the best from the Gitlab web API and Requests.

It’s far to be perfect as for example, it does not restore original authorship of issues and notes.

#! /usr/bin/env python

import zeep
import gitlab
import re

# Read a cheap configuration file from the current directory
with open('mantis2gitlab.conf') as f:
    mantis_url = f.readline().strip()
    mantis_user = f.readline().strip()
    mantis_passwd = f.readline().strip()
    gitlab_url = f.readline().strip()
    gitlab_token = f.readline().strip()
    gitlab_group = f.readline().strip()

mantis = zeep.Client(mantis_url + '/api/soap/mantisconnect.php?wsdl').service
gl = gitlab.Gitlab(gitlab_url, gitlab_token)
gl_group =[0]
gl_projects = {}
for p in gl.group_projects.list(, all=True):
    gl_projects[] = p

mantis_projects = mantis.mc_projects_get_user_accessible(mantis_user, mantis_passwd)
for mantis_project in mantis_projects._value_1:
    # This is my naming rule, adapt to yours
    gitlab_project_name =
    gl_project_id = gl_projects[gitlab_project_name].id
    mantis_issues = mantis.mc_project_get_issues(mantis_user, mantis_passwd,, 0, -1)
    print "Project", gitlab_project_name
    for mantis_issue in mantis_issues._value_1:
        print mantis_issue.summary
        description = mantis_issue.description
        # avoid spurious reference
        if"(#[0-9]+\s)", description):
            description = '```\n' + description + '\n```\n'
        if != mantis_user.lower():
            description += '\n(Mantis bug reported by ' + mantis_issue.reporter.real_name + ')'
        gl_issue = gl.project_issues.create({
            'title': mantis_issue.summary,
            'description': description,
            'created_at': mantis_issue.date_submitted.isoformat()
        }, project_id = gl_project_id)

        if mantis_issue.notes:
            for note in mantis_issue.notes._value_1:
                body = note.text
                if and != mantis_user.lower():
                    body += '\n(Mantis note by ' + note.reporter.real_name + ')'
                # use raw API to set the date
                gl._raw_post('/projects/%d/issues/%d/notes' % (gl_project_id,, data = {
                    'body': body,
                    'created_at': note.date_submitted.isoformat()

        if in ['resolved', 'closed']:
            gl._raw_put('/projects/%d/issues/%d' % (gl_project_id,, data = {
                'state_event': 'close',
                'updated_at': mantis_issue.last_updated.isoformat()

When writting this script I had to revert the convert process serveral time. Here is how I did on my Gitlab 8.12.3 instance:

docker exec -it gitlab_web_1 su - gitlab-psql
export COLMUNS=200
/opt/gitlab/embedded/bin/psql -h /var/opt/gitlab/postgresql -d gitlabhq_production
select id,name from projects ;

Assuming we want to clear the project 2 issues:

delete from issues where project_id=2 ;
delete from notes where project_id=2 and (noteable_type='Issue' or noteable_type='Commit') ;
Tags: , ,