Latest posts for tag truelite
Yesterday we were in an airport. We tried to connect to the airport "free" wifi. It had a captive portal that asked for a lot of personal information before one could maybe get on the internet, and we gave up. Bologna Airport, no matter what they do to pretend that they like you, it's always clear that they don't.
I looked at the captive portal screen and I said: «ah yes, "free" wifi. Free as in Facebook».
We figured that we had an expression that will want to be reused.
Now that I have a CalDAV server that syncs with my phone I would like to use it from my desktop.
It looks like akonadi is able to sync with CalDAV servers, so I'm giving it a try.
First thing first is to give a meaning to the arbitrary name of this thing. Wikipedia says it is the oracle goddess of justice in Ghana. That still does not hint at all at personal information servers, but seems quite nice. Ok. I gave up with software having purpose-related names ages ago.
# apt-get install akonadi-server akonadi-backend-postgresql
Akonadi wants a SQL database as a backend. By default it uses MySQL, but I had enough of MySQL ages ago.
I tried SQLite but the performance with it is terrible. Terrible as in, it takes 2 minutes between adding a calendar entry and having it show up in the calendar. I'm fascinated by how Akonadi manages to use SQLite so badly, but since I currently just want to get a job done, next in line is PostgreSQL:
# su - postgres
$ createuser enrico
$ psql postgres
postgres=# alter user enrico createdb;
Then as enrico
:
$ createdb akonadi-enrico
$ cat <<EOT > ~/.config/akonadi/akonadiserverrc
[%General]
Driver=QPSQL
[QPSQL]
Name=akonadi-enrico
StartServer=false
Host=
Options=
ServerPath=
InitDbPath=
I can now use kontact to connect Akonadi to my CalDAV server and it works nicely, both with calendar and with addressbook entries.
KDE has at least two clients for Akonadi: Kontact, which is a kitchen sink application similar to Evolution, and KOrganizer, which is just the calendar and scheduling component of Kontact.
Both work decently, and KOrganizer has a pretty decent startup time. I now have a usable desktop PIM application that is synced with my phone. W00T!
Next step is to port my swift little calendar display tool to use Akonadi as a back-end.
Four months ago I wrote this somewhere:
Seeing a DD saying "this new dbus stuff scares me" would make most debian users scared. Seeing a DD who has an idea of what is going on, and who can explain it, would be an interesting and exciting experience.
So, let's be exemplary, competent and patient. Or at least, competent. Some may like or not like the changes, but do we all understand what is going on? Will we all be able to support our friends and customers running jessie?
I confess that although I understand the need for it, I don't feel competent enough to support systemd-based machines right now.
So, are we maybe in need of help, cheat sheets, arsenals of one-liners, diagnostic tools?
Maybe a round of posts on -planet like "one debian package a day" but with new features that jessie will have, and how to understand them and take advantage of them?
That was four months ago. In the meantime, I did some work, and it got better for me.
Yesterday, however, I've seen an experienced Linux person frustrated because the shutdown function of the desktop was doing nothing whatsoever. Today I found John Goerzen's post on planet.
I felt like some more diagnostic tools were needed, so I spent the day making seat-inspect.
seat-inspect tries to make the status of the login/seat system visible, to help with understanding and troubleshooting.
The intent of running the code is to have an overview of the system status, both to see what the new facilities are about, and to figure out if there is something out of place.
The intent of reading the code is to have an idea of how to use these facilities: the code has been written to be straightforward and is annotated with relevant bits from the logind API documentation.
seat-inspect is not a finished tool, but a starting point. I put it on github hoping that people will fork it and add their own extra sanity checks and warnings, so that it can grow into a standard thing to run if a system acts weird.
As it is now, it should be able to issue warnings if some bits are missing for network-manager or shutdown functions to work correctly. I haven't really tested that, though, because I don't have a system at hand where they are currently not working fine.
Another nice thing of it is that when running seat-inspect -v
you get a dump
of what logind/consolekit think about your system. I found it an interesting
way to explore the new functionalities that we recently grew. The same can be
done, and in more details, with loginctl
calls, but I lacked a summary.
After writing this I feel a bit more competent, probably enough to sit at somebody's computer and poke into loginctl bits. I highly recommend the experience.
I am experimenting with showing progress on the terminal for a subcommand that is being run, showing what is happening without scrolling away the output of the main program, and I came out with this little toy. It shows the last X lines of a subcommand output, then gets rid of everything after the command has ended.
Usability-wise, it feels like a tease to me: it looks like I'm being shown all sorts of information then they are taken away from me before I managed to make sense of them. However, I find it cute enough to share:
#!/usr/bin/env python3 #coding: utf-8 # Copyright 2015 Enrico Zini <enrico@enricozini.org>. Licensed under the terms # of the GNU General Public License, version 2 or any later version. import argparse import fcntl import select import curses import contextlib import subprocess import os import sys import collections import shlex import shutil import logging def stream_output(proc): """ Take a subprocess.Popen object and generate its output, line by line, annotated with "stdout" or "stderr". At process termination it generates one last element: ("result", return_code) with the return code of the process. """ fds = [proc.stdout, proc.stderr] bufs = [b"", b""] types = ["stdout", "stderr"] # Set both pipes as non-blocking for fd in fds: fcntl.fcntl(fd, fcntl.F_SETFL, os.O_NONBLOCK) # Multiplex stdout and stderr with different prefixes while len(fds) > 0: s = select.select(fds, (), ()) for fd in s[0]: idx = fds.index(fd) buf = fd.read() if len(buf) == 0: fds.pop(idx) if len(bufs[idx]) != 0: yield types[idx], bufs.pop(idx) types.pop(idx) else: bufs[idx] += buf lines = bufs[idx].split(b"\n") bufs[idx] = lines.pop() for l in lines: yield types[idx], l res = proc.wait() yield "result", res @contextlib.contextmanager def miniscreen(has_fancyterm, name, maxlines=3, silent=False): """ Show the output of a process scrolling in a portion of the screen. has_fancyterm: true if the terminal supports fancy features; if false, just write lines to standard output name: name of the process being run, to use as a header maxlines: maximum height of the miniscreen silent: do nothing whatsoever, used to disable this without needing to change the code structure Usage: with miniscreen(True, "my process", 5) as print_line: for i in range(10): print_line(("stdout", "stderr")[i % 2], "Line #{}".format(i)) """ if not silent and has_fancyterm: # Discover all the terminal control sequences that we need output_normal = str(curses.tigetstr("sgr0"), "ascii") output_up = str(curses.tigetstr("cuu1"), "ascii") output_clreol = str(curses.tigetstr("el"), "ascii") cols, lines = shutil.get_terminal_size() output_width = cols fg_color = (curses.tigetstr("setaf") or curses.tigetstr("setf") or "") sys.stdout.write(str(curses.tparm(fg_color, 6), "ascii")) output_lines = collections.deque(maxlen=maxlines) def print_lines(): """ Print the lines in our buffer, then move back to the beginning """ sys.stdout.write("{} progress:".format(name)) sys.stdout.write(output_clreol) for msg in output_lines: sys.stdout.write("\n") sys.stdout.write(msg) sys.stdout.write(output_clreol) sys.stdout.write(output_up * len(output_lines)) sys.stdout.write("\r") try: print_lines() def _progress_line(type, line): """ Print a new line to the miniscreen """ # Add the new line to our output buffer msg = "{} {}".format("." if type == "stdout" else "!", line) if len(msg) > output_width - 4: msg = msg[:output_width - 4] + "..." output_lines.append(msg) # Update the miniscreen print_lines() yield _progress_line # Clear the miniscreen by filling our ring buffer with empty lines # then printing them out for i in range(maxlines): output_lines.append("") print_lines() finally: sys.stdout.write(output_normal) elif not silent: def _progress_line(type, line): print("{}: {}".format(type, line)) yield _progress_line else: def _progress_line(type, line): pass yield _progress_line def run_command_fancy(name, cmd, env=None, logfd=None, fancy=True, debug=False): quoted_cmd = " ".join(shlex.quote(x) for x in cmd) log.info("%s running command %s", name, quoted_cmd) if logfd: print("runcmd:", quoted_cmd, file=logfd) # Run the script itself on an empty environment, so that what was # documented is exactly what was run proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env) with miniscreen(fancy, name, silent=debug) as progress: stderr = [] for type, val in stream_output(proc): if type == "stdout": val = val.decode("utf-8") if logfd: print("stdout:", val, file=logfd) log.debug("%s stdout: %s", name, val) progress(type, val) elif type == "stderr": val = val.decode("utf-8") if logfd: print("stderr:", val, file=logfd) stderr.append(val) log.debug("%s stderr: %s", name, val) progress(type, val) elif type == "result": if logfd: print("retval:", val, file=logfd) log.debug("%s retval: %d", name, val) retval = val if retval != 0: lastlines = min(len(stderr), 5) log.error("%s exited with code %s", name, retval) log.error("Last %d lines of standard error:", lastlines) for line in stderr[-lastlines:]: log.error("%s: %s", name, line) return retval parser = argparse.ArgumentParser(description="run a command showing only a portion of its output") parser.add_argument("--logfile", action="store", help="specify a file where the full execution log will be written") parser.add_argument("--debug", action="store_true", help="debugging output on the terminal") parser.add_argument("--verbose", action="store_true", help="verbose output on the terminal") parser.add_argument("command", nargs="*", help="command to run") args = parser.parse_args() if args.debug: loglevel = logging.DEBUG elif args.verbose: loglevel = logging.INFO else: loglevel = logging.WARN logging.basicConfig(level=loglevel, stream=sys.stderr) log = logging.getLogger() fancy = False if not args.debug and sys.stdout.isatty(): curses.setupterm() if curses.tigetnum("colors") > 0: fancy = True if args.logfile: logfd = open("output.log", "wt") else: logfd = None retval = run_command_fancy("miniscreen example", args.command, logfd=logfd) sys.exit(retval)
Cyanogenmod found an update, it downloaded it, then it rebooted to install it and nothing happened. It turns out that the update procedure cannot work if the zip file to install is in encrypted media, so a workaround is to move the zip into unencrypted external storage.
As far as I know, my Nexus 4 has no unencrypted external storage.
This is how I managed to upgrade it, I write it here so I can find it next time:
- enable USB debugging
adb pull /cmupdater/cm-11-20141115-SNAPSHOT-M12-mako.zip
adb reboot recovery
- choose "install zip from sideload"
adb sideload cm-11-20141115-SNAPSHOT-M12-mako.zip
radicale and DAVdroid appeal to me. Let's try to make the whole thing work.
A self-signed SSL certificate
Update: use this method
instead, to avoid apache complaining that server certificate is a CA
certificate
.
Generating the certificate:
openssl req -nodes -x509 -newkey rsa:2048 -keyout cal-key.pem -out cal-cert.pem -days 3650 [...] Country Name (2 letter code) [AU]:IT State or Province Name (full name) [Some-State]:Bologna Locality Name (eg, city) []: Organization Name (eg, company) [Internet Widgits Pty Ltd]:enricozini.org Organizational Unit Name (eg, section) []: Common Name (e.g. server FQDN or YOUR name) []:cal.enricozini.org Email Address []:postmaster@enricozini.org
Installing it on my phone:
openssl x509 -in cal-cert.pem -outform DER -out cal-cert.crt adb push cal-cert.crt /mnt/sdcard/ enrico --follow-instructions http://davdroid.bitfire.at/faq/entry/importing-a-certificate
Installing radicale in my VPS
Update: there is already a new version of radicale available in Debian testing.
An updated radicale package, with this patch to make it work with DAVDroid:
apt-get source radicale # I reviewed 063f7de7a2c7c50de5fe3f8382358f9a1124fbb6 git clone https://github.com/Kozea/Radicale.git Move the python code from git to the Debian source dch -v 0.10~enrico-1 "Pulled in the not yet released 0.10 work from upstream" debuild -us -uc -rfakeroot
Install the package:
# dpkg -i python-radicale_0.10~enrico0-1_all.deb # dpkg -i radicale_0.10~enrico0-1_all.deb
Create a system user to run it:
# adduser --system --disabled-password radicale
Configure it (/etc/radicale/config
) for mod_wsgi
with auth done by Apache:
# For brevity, this is my config file with comments removed [storage] # Storage backend # Value: filesystem | multifilesystem | database | custom type = filesystem # Folder for storing local collections, created if not present filesystem_folder = /var/lib/radicale/collections [logging] config = /etc/radicale/logging
Create the wsgi file to run it:
# mkdir /srv/radicale # cat <<EOT > /srv/radicale/radicale.wsgi import radicale radicale.log.start() application = radicale.Application() EOT # chown radicale.radicale /srv/radicale/radicale.wsgi # chmod 0755 /srv/radicale/radicale.wsgi
Make radicale commit to git
# apt-get install python-dulwich # cd /var/lib/radicale/collections # git init # chown radicale.radicale -R /var/lib/radicale/collections/.git
Apache configuration
Add a new site to apache:
$ cat /etc/apache2/sites-available/cal.conf # For brevity, this is my config file with comments removed <IfModule mod_ssl.c> <VirtualHost *:443> ServerName cal.enricozini.org ServerAdmin enrico@enricozini.org Alias /robots.txt /srv/radicale/robots.txt Alias /favicon.ico /srv/radicale/favicon.ico WSGIDaemonProcess radicale user=radicale group=radicale threads=1 umask=0027 display-name=%{GROUP} WSGIProcessGroup radicale WSGIScriptAlias / /srv/radicale/radicale.wsgi <Directory /srv/radicale> # WSGIProcessGroup radicale # WSGIApplicationGroup radicale # WSGIPassAuthorization On AllowOverride None Require all granted </Directory> <Location /> AuthType basic AuthName "Enrico's Calendar" AuthBasicProvider file AuthUserFile /usr/local/etc/radicale/htpasswd Require user enrico </Location> ErrorLog{APACHE_LOG_DIR}/cal-enricozini-org-error.log LogLevel warn CustomLog{APACHE_LOG_DIR}/cal-enricozini-org-access.log combined SSLEngine on SSLCertificateFile /etc/ssl/certs/cal.pem SSLCertificateKeyFile /etc/ssl/private/cal.key </VirtualHost> </IfModule>
Then enable it:
# a2ensite cal.conf # service apache2 reload
Create collections
DAVdroid seems to want to see existing collections on the server, so we create them:
$ apt-get install cadaver $ cat <<EOT > /tmp/empty.ics BEGIN:VCALENDAR VERSION:2.0 END:VCALENDAR EOT $ cat <<EOT > /tmp/empty.vcf BEGIN:VCARD VERSION:2.1 END:VCARD EOT $ cadaver https://cal.enricozini.org WARNING: Untrusted server certificate presented for `cal.enricozini.org': [...] Do you wish to accept the certificate? (y/n) y Authentication required for Enrico's Calendar on server `cal.enricozini.org': Username: enrico Password: **** dav:/> cd enrico/contacts.vcf/ dav:/> put /tmp/empty.vcf dav:/> cd ../calendar.ics/ dav:/> put /tmp/empty.ics dav:/enrico/calendar.ics/> ^D Connection to `cal.enricozini.org' closed.
DAVdroid configuration
- Add a new DAVdroid sync account
- Use server/username configuration
- For server, use https://
/ / - Add username and password
It should work.
Related links
Since systemd version 215, adding systemd.debug-shell
to the kernel command
line activates the debug shell on tty9 alongside the normal boot. I like the
idea of that, and I'd like to have it in my standard 'rescue' entry in my grub
menu.
Unfortunately, by default update-grub
does not allow to customize the rescue
menu entry options. I have just filed #766530
hoping for that to change.
After testing the patch I proposed for /etc/grub.d/10_linux
, I now have this
in my /etc/default/grub
, with some satisfaction:
GRUB_CMDLINE_LINUX_RECOVERY="systemd.log_target=kmsg systemd.log_level=debug systemd.debug-shell"
Further information:
Thanks to sjoerd and uau on #debian-systemd for their help.
Lo spelling internazionale è troppo globalizzato, e volete recuperare un attimo la dimensione del posto dove siete nati e cresciuti?
Da oggi c'è questo script che fa per voi: gli dite dove abitate, e lui vi crea lo spelling a chilometri zero.
$ git clone git@gitorious.org:trespolo/osmspell.git $ cd osmspell $ ./osmspell "San Giorgio di Piano" 1: San Giorgio di Piano, BO, EMR, Italia 2: San Giorgio di Piano, Via Codronchi, San Giorgio di Piano, BO, EMR, Italia 3: San Giorgio Di Piano, Via Libertà, San Giorgio di Piano, BO, EMR, Italia Choose one: 1 Center: 44.6465332, 11.3790398 A Argelato, Altedo B Bentivoglio, Bologna, Boschi C Cinquanta, Castagnolo Minore, Castel Maggiore, Cento D Dosso E Eremo di Tizzano F Funo di Argelato, Finale Emilia, Ferrara, Fiesso G Gherghenzano, Galliera, Gesso I Il Cucco, Irnerio, Idice L Località Fortuna, Lovoleto, Lippo M Malacappa, Massumatico, Minerbio, Marano N Navile O Osteriola, Ozzano dell'Emilia, Oca P Piombino, Padulle, Poggio Renatico, Piave Q Quarto Inferiore, Quattrina R Rubizzano, Renazzo, Riale S San Giorgio di Piano, Saletto T Torre Verde, Tintoria, Tombe U Uccellino V Venezzano Mascarino, Vigarano Mainarda, Veduro X XII Morelli Z Zenerigolo, Zola Predosa
I dati vengono da OSM, e lo script è un ottimo esempio di come usarne la API di geolocazione (veloci) e la API di query geografica (lenta).
Update: source code is now here.