Categoría: linux

  • Acceso a Tailscale sin Privilegios Root: Android como Gateway de Red con Termux

    Termux y Taiscale para usar Android como un servidor totalmente funcional

    En el mundo de la seguridad informática y la administración de sistemas, a menudo nos encontramos con máquinas donde no podemos o no queremos instalar software que requiera privilegios de administrador. Ya sea por políticas corporativas, seguridad, o simplemente por mantener un sistema limpio, la necesidad de acceder a redes privadas sin comprometer el sistema host es real.

    Hoy les comparto una solución elegante: usar un dispositivo Android como puente para acceder a toda tu red Tailscale, sin instalar absolutamente nada con privilegios root en tu máquina principal.

    La Arquitectura

    macOS ──► Android ──► Tailscale ──► Servers
      │       (Termux)    Network
      │           │                         ▲
      └─SSH──────►│                         │
                socat tunnels───────────────┘

    Stack de Software

    En Android:

    • Tailscale: Aplicación oficial desde Play Store
    • Termux: Terminal emulator y entorno Linux
    • OpenSSH: Servidor SSH en Termux
    • socat: Herramienta para crear túneles de red

    En macOS/Linux:

    • SSH: Cliente nativo del sistema (¡nada más!)

    Configuración Paso a Paso

    1. Configurar Android como Exit Node

    En la aplicación Tailscale de Android:

    • Ir a Settings → Exit node
    • Activar «Run as exit node»
    • Aprobar el nodo desde la consola admin de Tailscale

    2. Preparar Termux

    Instalar Termux desde F-Droid o Play Store, luego:

    # Actualizar e instalar herramientas necesarias
    pkg update && pkg upgrade
    pkg install openssh socat net-tools
    
    # Iniciar servidor SSH
    sshd
    

    El servidor SSH de Termux escucha en el puerto 8022 por defecto.

    3. Activar Hotspot y Conectar

    1. Activar el hotspot/tethering en Android
    2. Conectar tu máquina al hotspot
    3. Encontrar la IP del gateway (que será Android):
    # En macOS/Linux
    route -n get default | grep gateway
    

    4. Crear Túneles con socat

    Una vez conectado por SSH a Termux:

    # Conectar a Termux desde tu máquina
    ssh -p 8022 u0_aXXX@IP_GATEWAY
    
    # En Termux, crear túnel hacia servidor en Tailscale
    socat TCP-LISTEN:2222,fork,reuseaddr TCP:100.x.x.x:22
    

    Donde 100.x.x.x es la IP de Tailscale del servidor destino.

    5. Conectar al Servidor Final

    Desde tu máquina, ahora puedes conectar al servidor remoto a través del túnel:

    ssh -p 2222 usuario@IP_GATEWAY
    

    Casos de Uso

    Esta configuración es perfecta para:

    • Máquinas corporativas donde no puedes instalar VPNs
    • Sistemas temporales donde no quieres dejar rastro
    • Debugging remoto cuando necesitas acceso rápido
    • Mantener un sistema limpio sin daemons adicionales

    Optimizaciones y Automatización

    Para uso frecuente, puedes:

    • Configurar claves SSH para acceso sin contraseña
    • Usar tmux en Termux para mantener sesiones persistentes
    • Crear scripts que automaticen la detección de IPs y creación de túneles
    • Configurar múltiples túneles para diferentes servidores simultáneamente

    Consideraciones de Seguridad

    • Solo usar en redes donde confíes (tu propio hotspot)
    • Configurar SSH con autenticación por clave, nunca contraseña
    • El tráfico entre Android y los servidores viaja encriptado por Tailscale
    • El hotspot crea una red aislada entre tu dispositivo y Android

    Conclusión

    Esta solución demuestra que con un poco de creatividad, podemos sortear limitaciones técnicas sin comprometer la seguridad. Android se convierte en un poderoso gateway de red, Tailscale provee la conectividad segura, y tu máquina principal permanece limpia y sin modificaciones de sistema.

    ¿El resultado? Acceso completo a tu infraestructura privada usando solo herramientas estándar y un teléfono que probablemente ya llevas contigo.


    ¿Has implementado soluciones similares? ¿Qué otros usos creativos le darías a esta arquitectura? Comparte tus ideas en los comentarios.

  • From Documentation to Distribution: The Complete Stremio Debian Packaging Journey

    From Documentation to Distribution: The Complete Stremio Debian Packaging Journey

    How a simple documentation contribution evolved into a full-scale packaging solution with automated CI/CD, multi-distribution support, and deep technical problem-solving

    Author: Juan Manuel Méndez Rey
    Date: October 30, 2025
    Reading Time: 25 minutes
    Technical Level: Advanced


    The Beginning: A Documentation Gap

    Several years ago, while working with Stremio on Debian systems, I encountered the familiar frustration of Linux users everywhere: a great application with poor installation documentation. The official Stremio releases worked fine on some distributions, but Debian users were left to figure out dependencies, compilation steps, and integration challenges on their own.

    That’s when I contributed the original DEBIAN.md file to the Stremio shell repository. It was a straightforward build guide—install these dependencies, run these commands, copy these files. Simple, but functional.

    Years passed. Dependencies changed. Qt versions evolved. The simple build instructions became increasingly unreliable on modern Debian systems, and the GitHub issues piled up with frustrated users unable to compile Stremio.


    The Problem Grows

    By 2025, the situation had become untenable:

    • Dependency conflicts: The upstream .deb package required libmpv1, but modern Debian ships libmpv2
    • FHS violations: Upstream installed everything to /opt, violating Debian filesystem standards
    • Missing QML modules: Critical Qt5 components weren’t documented as dependencies
    • Compilation complexity: Users needed to install 15+ build dependencies to compile from source
    • No proper integration: Desktop files, icons, and system integration required manual work
    • The upstream .deb package is outdated, it is providing the 4.4.168 version.
    • The list continues…

    The GitHub issues were a testament to user frustration—dozens of reports about compilation failures, missing dependencies, and broken installations.


    The Debian Way: Proper Packaging

    Rather than continue patching documentation, I remembered a discussion with my friend, Arturo, about properly packaging Stremio for Debian, he created a RFP (Request for Package) for Stremio in 2020. Years passed and I went into my usual day to day work.
    This past month I decided I had to fulfill my old dream of becoming an official Debian contributor, so I decided to solve this properly through the Debian packaging system. In late 2025, I filed an Intent To Package (ITP) with Debian:

    The goal was simple: create properly-packaged Debian packages that would eventually enter the official Debian archive.

    Packaging Challenges

    Stremio presents unique packaging challenges:

    1. License separation: The desktop client is GPL-3.0 (free), but the streaming server is proprietary
    2. Modern dependencies: Requires current Qt5 WebEngine and libmpv versions
    3. Complex build system: Qt5 + Node.js + WebAssembly components
    4. Desktop integration: Proper icon installation, MIME types, and .desktop files
    5. Bundled dependencies: Upstream used git submodules for everything

    Following Debian policy, I separated the components:

    • stremio package (main/free) – GPL desktop client v4.4.169
    • stremio-server package (non-free) – Proprietary streaming server v4.20.12

    Technical Deep Dive: System Library Migration

    The most challenging aspect was replacing ALL bundled git submodules with Debian system libraries. This wasn’t just about dependencies—it required fixing fundamental runtime issues.

    Challenge 1: QtWebEngine Initialization Crash 🔥 CRITICAL

    Problem: Application crashed immediately on startup:

    Segmentation fault (core dumped)

    Root Cause Analysis:

    # GDB backtrace showed:
    #0  QQmlApplicationEngine::QQmlApplicationEngine()
    #1  main (argc=1, argv=0x7fffffffdc58) at main.cpp:120

    QtWebEngine must be initialized before QApplication constructor, but upstream code created QApplication first.

    Solution: Added critical initialization call in main.cpp:

    #include <QtWebEngine/QtWebEngine>
    
    int main(int argc, char *argv[]) {
        // CRITICAL: Initialize QtWebEngine before QApplication
        QtWebEngine::initialize();
    
        QApplication app(argc, argv);
        // ... rest of code
    }

    Impact: Resolved 100% of QML engine crashes. This single line prevents all QtWebEngine initialization failures.

    Patch: 0007-add-qtwebengine-initialize-fix.patch


    Challenge 2: SingleApplication Threading Incompatibility 🔥 CRITICAL

    Problem: System libsingleapplication-dev v3.3.4 caused segmentation faults when used with QQmlApplicationEngine.

    Investigation:

    # Test with system library:
    sudo apt install libsingleapplication-dev
    # Build and run: Segmentation fault
    
    # Test without SingleApplication:
    # Remove from CMakeLists.txt: Works perfectly

    Root Cause: System library sets up threading context incompatible with Qt5 QML engine initialization. The library uses internal threading mechanisms that conflict with QQmlApplicationEngine’s event loop.

    Solution: Custom CompatibleSingleApp implementation. This is also to replace one of the bundled submodules that recently modified its MIT license into a dubious license that could be incompatible for Debian DFSG guidelines. See https://github.com/itay-grudev/SingleApplication/issues/210

    • Pure QApplication subclass
    • IPC via QLocalSocket/QLocalServer
    • No threading conflicts
    • Full single-instance functionality

    Implementation (compatible_singleapp.h):

    #ifndef COMPATIBLE_SINGLEAPP_H
    #define COMPATIBLE_SINGLEAPP_H
    
    #include <QApplication>
    #include <QLocalServer>
    #include <QLocalSocket>
    
    class CompatibleSingleApp : public QApplication {
        Q_OBJECT
    
    public:
        CompatibleSingleApp(int &argc, char **argv, const QString &appId);
        ~CompatibleSingleApp();
    
        bool isPrimary() const { return m_isPrimary; }
        bool sendMessage(const QString &message);
    
    signals:
        void receivedMessage(const QString &message);
    
    private slots:
        void handleNewConnection();
    
    private:
        bool m_isPrimary;
        QLocalServer *m_server;
        QString m_socketName;
    };
    
    #endif

    Implementation (compatible_singleapp.cpp):

    #include "compatible_singleapp.h"
    #include <QLocalSocket>
    #include <QCryptographicHash>
    
    CompatibleSingleApp::CompatibleSingleApp(int &argc, char **argv, const QString &appId)
        : QApplication(argc, argv), m_isPrimary(false), m_server(nullptr) {
    
        // Generate unique socket name
        m_socketName = QString("stremio-") +
            QString::fromUtf8(QCryptographicHash::hash(appId.toUtf8(),
                                                         QCryptographicHash::Sha256).toHex().left(16));
    
        // Try to connect to existing instance
        QLocalSocket socket;
        socket.connectToServer(m_socketName);
    
        if (socket.waitForConnected(500)) {
            // Another instance is running
            m_isPrimary = false;
            socket.disconnectFromServer();
            return;
        }
    
        // We're the primary instance
        m_isPrimary = true;
    
        // Create server for IPC
        m_server = new QLocalServer(this);
        QLocalServer::removeServer(m_socketName);
    
        if (m_server->listen(m_socketName)) {
            connect(m_server, &QLocalServer::newConnection,
                    this, &CompatibleSingleApp::handleNewConnection);
        }
    }
    
    CompatibleSingleApp::~CompatibleSingleApp() {
        if (m_server) {
            m_server->close();
            QLocalServer::removeServer(m_socketName);
        }
    }
    
    bool CompatibleSingleApp::sendMessage(const QString &message) {
        if (m_isPrimary) return false;
    
        QLocalSocket socket;
        socket.connectToServer(m_socketName);
    
        if (!socket.waitForConnected(1000)) return false;
    
        QByteArray data = message.toUtf8();
        socket.write(data);
        socket.waitForBytesWritten();
        socket.disconnectFromServer();
    
        return true;
    }
    
    void CompatibleSingleApp::handleNewConnection() {
        QLocalSocket *socket = m_server->nextPendingConnection();
    
        if (socket) {
            connect(socket, &QLocalSocket::readyRead, this, [this, socket]() {
                QByteArray data = socket->readAll();
                emit receivedMessage(QString::fromUtf8(data));
                socket->deleteLater();
            });
        }
    }

    Results:

    • ✅ Zero threading conflicts
    • ✅ Full single-instance behavior
    • ✅ Message passing between instances
    • ✅ Clean integration with QQmlApplicationEngine

    Patches:

    • 0008-add-compatible-singleapp-implementation.patch
    • 0009-remove-system-singleapplication-add-compatible.patch

    Challenge 3: QProcess Environment Variables for Node.js Server 🔥 CRITICAL

    Problem: Streaming server failed to start with cryptic error:

    server-crash 0 null
    TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined
        at Object.join (node:path:1292:7)

    Investigation:

    # Manual server test works:
    $ /usr/bin/node /usr/share/stremio/server.js
    EngineFS server started at http://127.0.0.1:11470
    
    # But QProcess launch fails:
    timeout 15s stremio
    # Error: server-crash 0 null

    Root Cause: QProcess does not inherit environment variables by default. Node.js server.js requires:

    • HOME – for configuration directory (~/.stremio-server)
    • USER – for process identification
    • PWD – for relative path resolution

    Solution: Explicit environment setup in stremioprocess.cpp:

    void Process::start(QStringList args) {
        // Set up environment variables for Node.js server
        QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
    
        // Ensure essential environment variables are set for server.js
        if (!env.contains("HOME")) {
            env.insert("HOME", QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
        }
        if (!env.contains("USER")) {
            env.insert("USER", qgetenv("USER"));
        }
        if (!env.contains("PWD")) {
            env.insert("PWD", QDir::currentPath());
        }
    
        this->setProcessEnvironment(env);
    
        // Now start the process
        QProcess::start(this->program(), args);
    }

    Verification:

    # After fix:
    $ timeout 15s build/stremio 2>&1 | grep -A 5 "hls executables"
    hls executables located -> { ffmpeg: '/usr/bin/ffmpeg', ffsplit: null }
    Using app path -> /home/user/.stremio-server
    Enabling casting...
    Discovery of new external device "mpv" - MPV
    EngineFS server started at http://127.0.0.1:11470

    Impact: Complete resolution of streaming functionality. Users can now stream media via BitTorrent, use casting, and access all server features.

    Patch: 0011-fix-qprocess-environment-for-server-launch.patch


    Challenge 4: System Tray Widget Creation Timing

    Problem: Warning on startup:

    QWidget: Cannot create a QWidget without QApplication

    Root Cause: SystemTray widget created before QML engine fully initialized.

    Solution: Delayed creation until after engine->load() completes:

    // main.cpp
    QQmlApplicationEngine *engine = new QQmlApplicationEngine();
    engine->load(QUrl("qrc:/main.qml"));
    
    // NOW create system tray (after QML loaded)
    SystemTray *tray = new SystemTray(&app);

    Result: Clean startup without widget warnings.


    Build System Architecture: Dual Build Support

    The project maintains two parallel build systems for flexibility:

    CMake System (Primary)

    Used by release.makefile and package builds:

    # CMakeLists.txt
    cmake_minimum_required(VERSION 3.16)
    project(stremio)
    
    set(CMAKE_CXX_STANDARD 14)
    set(CMAKE_AUTOMOC ON)
    set(CMAKE_AUTORCC ON)
    
    find_package(Qt5 REQUIRED COMPONENTS Core Gui Widgets Qml Quick WebEngine DBus)
    find_package(PkgConfig REQUIRED)
    pkg_check_modules(MPV REQUIRED mpv)
    pkg_check_modules(OPENSSL REQUIRED openssl)
    
    # Sources including CompatibleSingleApp
    set(SOURCES
        main.cpp
        compatible_singleapp.cpp
        stremioprocess.cpp
        # ... other sources
    )
    
    # Headers for MOC
    set(HEADERS
        mainapplication.h
        compatible_singleapp.h
        stremioprocess.h
        # ... other headers
    )
    
    add_executable(stremio ${SOURCES} ${HEADERS} resources.qrc)
    
    target_link_libraries(stremio
        Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Qml Qt5::Quick Qt5::WebEngine Qt5::DBus
        ${MPV_LIBRARIES}
        ${OPENSSL_LIBRARIES}
    )
    
    install(TARGETS stremio DESTINATION bin)

    Build command:

    QT_DEFAULT_MAJOR_VERSION=5 make -f release.makefile
    # Result: 293KB optimized binary

    qmake System (Legacy)

    Used for manual builds and development:

    # stremio.pro
    QT += core gui widgets qml quick webengine dbus
    CONFIG += c++14
    
    SOURCES += \
        main.cpp \
        compatible_singleapp.cpp \
        stremioprocess.cpp \
        # ... other sources
    
    HEADERS += \
        mainapplication.h \
        compatible_singleapp.h \
        stremioprocess.h \
        # ... other headers
    
    RESOURCES += resources.qrc
    
    # System libraries
    unix:!macx {
        CONFIG += link_pkgconfig
        PKGCONFIG += mpv openssl
    }
    
    target.path = /usr/bin
    INSTALLS += target

    Build command:

    QT_SELECT=5 qmake
    QT_SELECT=5 make
    # Result: 278KB optimized binary

    Both systems produce working binaries with 100% system libraries.


    Debian Packaging: The Proper Way

    Package Structure

    stremio (4.4.169+dfsg-1):

    debian/
    ├── changelog                    # Version history with ITP closure
    ├── control                      # Dependencies and package metadata
    ├── copyright                    # GPL-3.0+ licensing details
    ├── rules                        # Build instructions (dh-based)
    ├── patches/                     # Quilt patches for system integration
    │   ├── 0001-Fix-server.js-path-for-FHS-compliance.patch
    │   ├── 0002-disable-server-download.patch
    │   ├── 0004-minimal-qthelper-integration.patch
    │   ├── 0005-cmake-system-libraries-v4.4.169.patch
    │   ├── 0007-add-qtwebengine-initialize-fix.patch
    │   ├── 0008-add-compatible-singleapp-implementation.patch
    │   ├── 0009-remove-system-singleapplication-add-compatible.patch
    │   ├── 0010-fix-qmake-install-paths.patch
    │   └── 0011-fix-qprocess-environment-for-server-launch.patch
    ├── stremio.desktop              # Desktop integration
    ├── stremio.install              # File installation rules
    ├── watch                        # Upstream version monitoring
    └── source/
        └── format                   # 3.0 (quilt) format

    Key debian/control sections:

    Source: stremio
    Section: video
    Priority: optional
    Maintainer: Juan Manuel Méndez Rey <vejeta@gmail.com>
    Build-Depends:
        debhelper-compat (= 13),
        cmake,
        qtbase5-dev,
        qt5-qmake,
        qt5-qmake-bin,
        qtdeclarative5-dev,
        qtwebengine5-dev,
        qttools5-dev,
        qml-module-qtwebchannel,
        qml-module-qt-labs-platform,
        qml-module-qtwebengine,
        qml-module-qtquick-dialogs,
        qml-module-qtquick-controls,
        qml-module-qt-labs-settings,
        qml-module-qt-labs-folderlistmodel,
        libmpv-dev,
        libssl-dev,
        nodejs,
        npm,
        pkg-kde-tools
    Standards-Version: 4.6.2
    Homepage: https://www.stremio.com/
    Vcs-Git: https://salsa.debian.org/mendezr/stremio.git
    Vcs-Browser: https://salsa.debian.org/mendezr/stremio
    
    Package: stremio
    Architecture: amd64
    Depends: ${shlibs:Depends}, ${misc:Depends},
             nodejs,
             mpv,
             librsvg2-2,
             qml-module-qtwebengine,
             qml-module-qtwebchannel,
             qml-module-qt-labs-platform,
             qml-module-qtquick-controls,
             qml-module-qtquick-dialogs,
             qml-module-qt-labs-settings,
             qml-module-qt-labs-folderlistmodel,
             qtbase5-dev-tools
    Description: Modern media center for streaming video content
     Stremio is a video streaming application that aggregates content from
     various sources. It features a modern Qt5/QML interface with support
     for add-ons, local playback via MPV, and integration with streaming
     services.
     .
     This package provides the desktop client with GPL-licensed components.

    Build process:

    # Development build
    QT_DEFAULT_MAJOR_VERSION=5 dpkg-buildpackage -us -uc
    
    # Package build with signature
    QT_DEFAULT_MAJOR_VERSION=5 dpkg-buildpackage -sa
    
    # Clean environment build
    sudo pbuilder build ../stremio_4.4.169+dfsg-1.dsc

    stremio-server Package (Independent Versioning)

    Critical Decision: Server uses independent version number tracking its upstream:

    Source: stremio-server
    Section: non-free/video
    Version: 4.20.12-1
    
    Package: stremio-server
    Architecture: all
    Depends: ${misc:Depends}, nodejs (>= 12)
    Description: BitTorrent streaming server for Stremio (proprietary)
     Proprietary streaming server component providing BitTorrent support,
     HLS transcoding, and casting functionality for Stremio.
     .
     Version 4.20.12 corresponds to upstream server.js release.

    Why independent versioning?

    • Server has different release cycle than client
    • Upstream server.js updates independently (v4.20.x)
    • Client updates independently (v4.4.x)
    • Follows industry practice: VS Code, Docker Desktop, Firefox ESR

    debian/copyright documents source:

    Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
    Upstream-Name: stremio-server
    Source: https://dl.strem.io/server/v4.20.12/desktop/server.js
    Comment: Pre-downloaded server.js included in source package to comply
     with Debian Policy prohibiting network access during builds.

    Beyond Debian: The Wolfi Contribution

    While working on Debian packaging, I also contributed Stremio packages to Wolfi Linux, the security-focused distribution used by Chainguard. This involved:

    • Melange build files: Cloud-native package format
    • Security hardening: ASLR, stack protection, RELRO
    • OSI license compliance: GPL components only (no proprietary server, the same server.js we separated in a non-free package for Debian)
    • Reproducible builds: Hermetic build environment

    Melange configuration example:

    package:
      name: stremio
      version: 4.4.169
      epoch: 0
      description: Modern media center for video streaming
      license: GPL-3.0-or-later
    
    environment:
      contents:
        packages:
          - qt5-qtbase-dev
          - qt5-qtdeclarative-dev
          - qt5-qtwebengine-dev
          - mpv-dev
          - openssl-dev
    
    pipeline:
      - uses: cmake/configure
      - uses: cmake/build
      - uses: cmake/install
    
    subpackages:
      - name: stremio-doc
        description: Documentation for stremio

    I used this parallel effort as an exercise to learn how different distributions do proper packaging across different distribution ecosystems.

    Pull Request:
    https://github.com/wolfi-dev/os/pull/69098
    GitHub Gists with examples of usage:
    https://gist.github.com/vejeta/859f100ef74b87eadf7f7541ead2a2b1


    The Distribution Challenge: GitHub-Powered APT Repository

    Official Debian inclusion takes time—months or years of review, testing, and refinement. Meanwhile, users needed a solution now. Traditional approaches like hosting packages on a personal server would create bandwidth and maintenance problems.

    The solution: Modern APT repository hosting using GitHub infrastructure.

    Architecture Overview

    ┌─────────────────────────────────────────────────────────┐
    │              Canonical Sources (Salsa)                  │
    │  https://salsa.debian.org/mendezr/stremio               │
    │  https://salsa.debian.org/mendezr/stremio-server        │
    └────────────────────┬────────────────────────────────────┘
                         │
                         │ Instant Webhook + Weekly Cron
                         ▼
    ┌─────────────────────────────────────────────────────────┐
    │          GitHub Repository (Build System)               │
    │      https://github.com/vejeta/stremio-debian           │
    │                                                          │
    │  • stremio-client/ (git submodule → Salsa)             │
    │  • stremio-server/ (git submodule → Salsa)             │
    │  • .github/workflows/                                   │
    │      - build-and-release.yml                            │
    │      - deploy-repository.yml                            │
    │      - sync-from-salsa.yml                              │
    │  • repository-scripts/                                  │
    │      - generate-apt-repo.sh                             │
    │      - sign-repository.sh                               │
    └────────────────────┬────────────────────────────────────┘
                         │
           ┌─────────────┴─────────────┐
           │                           │
           ▼                           ▼
    ┌──────────────┐          ┌────────────────┐
    │GitHub Releases│         │ GitHub Pages   │
    │              │          │                │
    │ Binary .debs │          │ APT Repository │
    │ Source files │          │ Signed metadata│
    │ Build logs   │          │ Global CDN     │
    └──────────────┘          └────────────────┘
                                       │
                                       ▼
                              ┌────────────────┐
                              │ Custom Domain  │
                              │ debian.vejeta  │
                              │     .com       │
                              └────────────────┘

    Multi-Distribution Strategy: Matrix Builds

    The Critical Discovery: Packages built on one Debian release don’t work on others due to ABI dependencies.

    Problem Example:

    # Package built on Debian Bookworm:
    $ dpkg -I stremio_4.4.169+dfsg-1_amd64.deb | grep Depends
    Depends: qtdeclarative-abi-5-15-8
    
    # But Debian Sid/Kali have:
    $ apt-cache show qtdeclarative5-dev | grep Provides
    Provides: qtdeclarative-abi-5-15-15
    
    # Result: Installation fails on Sid/Kali

    Solution: Build packages in native containers for each distribution:

    # .github/workflows/build-and-release.yml
    jobs:
      build-stremio-client:
        name: Build stremio (main/free) - ${{ matrix.distro }}
        runs-on: ubuntu-latest
        strategy:
          matrix:
            distro: [trixie, bookworm, sid, noble]
            include:
              - distro: trixie
                suite: stable
                os_type: debian
              - distro: bookworm
                suite: oldstable
                os_type: debian
              - distro: sid
                suite: unstable
                os_type: debian
              - distro: noble
                suite: lts
                os_type: ubuntu
        container:
          image: ${{ matrix.os_type }}:${{ matrix.distro }}
          options: --privileged
    
        steps:
          - name: Install build dependencies
            run: |
              apt-get update
              apt-get install -y \
                git git-buildpackage pristine-tar \
                debhelper-compat cmake \
                qtbase5-dev qt5-qmake qt5-qmake-bin \
                qtdeclarative5-dev qtwebengine5-dev qttools5-dev \
                qml-module-qtwebchannel qml-module-qt-labs-platform \
                qml-module-qtwebengine qml-module-qtquick-dialogs \
                qml-module-qtquick-controls qml-module-qt-labs-settings \
                qml-module-qt-labs-folderlistmodel \
                libmpv-dev libssl-dev nodejs npm pkg-kde-tools \
                devscripts lintian dpkg-dev fakeroot librsvg2-bin
    
          - name: Checkout repository with submodules
            uses: actions/checkout@v4
            with:
              fetch-depth: 0
              submodules: recursive
    
          - name: Configure git for gbp
            run: |
              git config --global user.email "vejeta@gmail.com"
              git config --global user.name "Juan Manuel Méndez Rey"
              git config --global --add safe.directory '*'
    
          - name: Create upstream tarball
            working-directory: stremio-client
            run: |
              VERSION=$(dpkg-parsechangelog -S Version | cut -d- -f1)
    
              # Try pristine-tar first
              if git rev-parse --verify pristine-tar >/dev/null 2>&1; then
                pristine-tar checkout ../stremio_${VERSION}.orig.tar.xz 2>/dev/null || \
                pristine-tar checkout ../stremio_${VERSION}.orig.tar.gz 2>/dev/null
              fi
    
              # Fallback to upstream tag
              if [ ! -f ../stremio_${VERSION}.orig.tar.* ]; then
                UPSTREAM_TAG=$(git tag -l "upstream/*" | grep -E "${VERSION%+*}" | tail -1)
                git archive --format=tar --prefix=stremio-${VERSION%+*}/ $UPSTREAM_TAG | \
                  xz > ../stremio_${VERSION}.orig.tar.xz
              fi
    
          - name: Build packages (source + binary)
            working-directory: stremio-client
            run: |
              QT_DEFAULT_MAJOR_VERSION=5 dpkg-buildpackage -us -uc -sa
    
          - name: Run lintian checks
            continue-on-error: true
            run: |
              lintian --info --display-info --pedantic stremio-client/../*.deb || true
    
          - name: Smoke test package (Ubuntu only)
            if: matrix.os_type == 'ubuntu'
            continue-on-error: true
            run: |
              echo "=== Ubuntu Package Smoke Test ==="
              apt install -y ./stremio-client/../*.deb || true
              which stremio && echo "✓ Binary found" || echo "✗ Binary not found"
              ldd /usr/bin/stremio | grep -E "(libQt5|libmpv|libcrypto)" || true
              export QT_QPA_PLATFORM=offscreen
              export QTWEBENGINE_DISABLE_SANDBOX=1
              timeout 10s stremio 2>&1 || echo "✓ GUI test completed"
    
          - name: Collect build artifacts
            run: |
              mkdir -p artifacts/stremio-client-${{ matrix.distro }}
    
              # Rename .deb with distro suffix
              for deb in stremio-client/../*.deb; do
                if [ -f "$deb" ]; then
                  filename=$(basename "$deb")
                  newname="${filename%.deb}-${{ matrix.distro }}.deb"
                  mv "$deb" "artifacts/stremio-client-${{ matrix.distro }}/$newname"
                fi
              done
    
              # Move other files
              mv stremio-client/../*.dsc artifacts/stremio-client-${{ matrix.distro }}/ 2>/dev/null || true
              mv stremio-client/../*.tar.* artifacts/stremio-client-${{ matrix.distro }}/ 2>/dev/null || true
              mv stremio-client/../*.buildinfo artifacts/stremio-client-${{ matrix.distro }}/ 2>/dev/null || true
              mv stremio-client/../*.changes artifacts/stremio-client-${{ matrix.distro }}/ 2>/dev/null || true
    
          - name: Upload build artifacts
            uses: actions/upload-artifact@v4
            with:
              name: stremio-client-packages-${{ matrix.distro }}
              path: artifacts/stremio-client-${{ matrix.distro }}/*.deb
              retention-days: 30

    Result: Each distribution gets packages with correct native dependencies:

    • debian:trixieqtdeclarative-abi-5-15-15
    • debian:bookwormqtdeclarable-abi-5-15-8
    • debian:sidqtdeclarable-abi-5-15-17
    • ubuntu:noble → Ubuntu-specific Qt5 dependencies

    APT Repository Generation

    Script: repository-scripts/generate-apt-repo.sh

    #!/bin/bash
    set -e
    
    PACKAGE_DIR="$1"    # packages/trixie/main
    REPO_DIR="$2"       # debian-repo
    SUITE="$3"          # trixie
    COMPONENT="$4"      # main
    
    echo "Generating APT repository for $SUITE/$COMPONENT"
    
    # Create directory structure
    mkdir -p "$REPO_DIR/dists/$SUITE/$COMPONENT/binary-amd64"
    mkdir -p "$REPO_DIR/pool/$SUITE/$COMPONENT"
    
    # Copy packages to pool
    if [ -d "$PACKAGE_DIR" ] && [ "$(ls -A $PACKAGE_DIR/*.deb 2>/dev/null)" ]; then
        cp "$PACKAGE_DIR"/*.deb "$REPO_DIR/pool/$SUITE/$COMPONENT/"
    fi
    
    # Generate Packages file
    cd "$REPO_DIR"
    dpkg-scanpackages --arch amd64 "pool/$SUITE/$COMPONENT" /dev/null > \
        "dists/$SUITE/$COMPONENT/binary-amd64/Packages"
    
    # Compress Packages file
    gzip -9 -k "dists/$SUITE/$COMPONENT/binary-amd64/Packages"
    
    echo "✓ Repository generated for $SUITE/$COMPONENT"

    APT Repository Structure:

    debian-repo/
    ├── dists/
    │   ├── trixie/
    │   │   ├── main/
    │   │   │   └── binary-amd64/
    │   │   │       ├── Packages
    │   │   │       └── Packages.gz
    │   │   ├── non-free/
    │   │   │   └── binary-amd64/
    │   │   │       ├── Packages
    │   │   │       └── Packages.gz
    │   │   ├── Release
    │   │   └── InRelease (GPG signed)
    │   ├── bookworm/
    │   │   └── [same structure]
    │   ├── sid/
    │   │   └── [same structure]
    │   └── noble/
    │       └── [same structure]
    ├── pool/
    │   ├── trixie/
    │   │   ├── main/
    │   │   │   └── stremio_4.4.169+dfsg-1_amd64.deb
    │   │   └── non-free/
    │   │       └── stremio-server_4.20.12-1_all.deb
    │   ├── bookworm/
    │   │   └── [same structure]
    │   ├── sid/
    │   │   └── [same structure]
    │   └── noble/
    │       └── [same structure]
    └── key.gpg

    Release File Generation with Checksums

    Workflow excerpt (.github/workflows/deploy-repository.yml):

    - name: Update Release files for all distributions
      run: |
        cd debian-repo
    
        update_release() {
          local SUITE=$1
    
          cat > dists/$SUITE/Release << EOF
        Origin: Stremio Debian Repository
        Label: Stremio
        Suite: $SUITE
        Codename: $SUITE
        Components: main non-free
        Architectures: amd64
        Description: Unofficial Debian packages for Stremio media center ($SUITE)
        Date: $(date -R -u)
        EOF
    
          # Add MD5Sum checksums
          echo "MD5Sum:" >> dists/$SUITE/Release
          find dists/$SUITE -type f ! -name "Release*" | while read file; do
              relative_path="${file#dists/$SUITE/}"
              md5=$(md5sum "$file" | awk '{print $1}')
              size=$(stat -c%s "$file")
              printf " %s %8d %s\n" "$md5" "$size" "$relative_path" >> dists/$SUITE/Release
          done
    
          # Add SHA1 checksums
          echo "SHA1:" >> dists/$SUITE/Release
          find dists/$SUITE -type f ! -name "Release*" | while read file; do
              relative_path="${file#dists/$SUITE/}"
              sha1=$(sha1sum "$file" | awk '{print $1}')
              size=$(stat -c%s "$file")
              printf " %s %8d %s\n" "$sha1" "$size" "$relative_path" >> dists/$SUITE/Release
          done
    
          # Add SHA256 checksums
          echo "SHA256:" >> dists/$SUITE/Release
          find dists/$SUITE -type f ! -name "Release*" | while read file; do
              relative_path="${file#dists/$SUITE/}"
              sha256=$(sha256sum "$file" | awk '{print $1}')
              size=$(stat -c%s "$file")
              printf " %s %8d %s\n" "$sha256" "$size" "$relative_path" >> dists/$SUITE/Release
          done
        }
    
        # Generate for all distributions
        update_release trixie
        update_release bookworm
        update_release sid
        update_release noble

    GPG Signing

    Script: repository-scripts/sign-repository.sh

    #!/bin/bash
    set -e
    
    REPO_DIR="$1"
    SUITE="$2"
    GPG_KEY_ID="$3"
    
    cd "$REPO_DIR/dists/$SUITE"
    
    # Clear sign Release file to create InRelease
    gpg --default-key "$GPG_KEY_ID" --clearsign --output InRelease Release
    
    # Detached signature for Release.gpg
    gpg --default-key "$GPG_KEY_ID" --armor --detach-sign --output Release.gpg Release
    
    echo "✓ Signed repository for $SUITE"

    GitHub Pages Deployment

    Workflow (simplified):

    - name: Setup Pages
      uses: actions/configure-pages@v4
    
    - name: Upload artifact
      uses: actions/upload-pages-artifact@v3
      with:
        path: debian-repo
    
    - name: Deploy to GitHub Pages
      uses: actions/deploy-pages@v4

    Result: APT repository served at https://debian.vejeta.com/ with:

    • ✅ Global CDN (CloudFlare)
    • ✅ HTTPS encryption
    • ✅ Unlimited bandwidth
    • ✅ Zero hosting costs
    • ✅ 99.9%+ uptime

    Critical Lessons Learned: Patch Development Best Practices

    During this project, I made significant efficiency mistakes in patch development. Here’s what I learned:

    The Inefficiency Problem

    What I did (5+ iterations of patch rework):

    1. Modified source files directly in working repository
    2. Generated patches from modified state
    3. Patches failed on clean upstream
    4. Repeated entire process multiple times

    Impact: ~70% wasted time in patch development

    The Correct Approach

    Efficient patch development workflow:

    # Step 1: Clean upstream baseline
    git clone --branch v4.4.169 https://github.com/Stremio/stremio-shell.git /tmp/patch-test
    cd /tmp/patch-test
    
    # Step 2: Analyze dependencies BEFORE making changes
    echo "=== Mapping file dependencies ==="
    grep -r "#include" *.cpp *.h | grep -v "Qt\|std"
    grep -r "class.*:" *.h
    grep -r "Q_OBJECT" *.h
    
    # Step 3: Make ONE fix at a time
    vim main.cpp  # Add QtWebEngine::initialize()
    git diff > /tmp/0007-qtwebengine-fix.patch
    
    # Step 4: Test patch application
    git checkout .
    patch -p1 < /tmp/0007-qtwebengine-fix.patch
    mkdir build && cd build && cmake .. && make
    
    # Step 5: If successful, continue to next fix
    # If failed, refine current patch before moving on

    Pre-Patch Analysis Template

    Before creating patches, ALWAYS complete this analysis:

    ## Files to Modify
    - [ ] main.cpp - QtWebEngine initialization
    - [ ] mainapplication.h - class definitions
    - [ ] CMakeLists.txt - build system
    - [ ] compatible_singleapp.h/cpp - new custom implementation
    
    ## Dependency Chain
    1. main.cpp includes → mainapplication.h
    2. mainapplication.h includes → singleapplication.h (to be replaced)
    3. CMakeLists.txt references → SingleApplication (to be removed)
    4. Qt MOC processes → Q_OBJECT classes (check for conflicts)
    
    ## Build Test Plan
    1. [ ] Clean cmake build
    2. [ ] Dependency verification (ldd)
    3. [ ] Runtime functionality test
    4. [ ] Package build test (dpkg-buildpackage)

    Validation Before «Ready» Declaration

    NEVER declare patches ready without:

    # MANDATORY validation workflow
    mkdir /tmp/patch-validation
    cd /tmp/patch-validation
    git clone --branch v4.4.169 <upstream-url> .
    
    # Apply ALL patches
    export QUILT_PATCHES=debian/patches
    quilt push -a || { echo "FAIL: Patch application"; exit 1; }
    
    # Complete build test
    mkdir build && cd build
    cmake .. && make || { echo "FAIL: Build"; exit 1; }
    
    # Package build test
    cd .. && dpkg-buildpackage -us -uc || { echo "FAIL: Package"; exit 1; }
    
    # Dependency check
    ldd build/stremio | grep -E "(libQt5|libmpv|libcrypto)"
    
    # ONLY NOW declare "patches ready"
    echo "✅ Validated and ready for production"

    This workflow prevents the «ready → fails → rework» cycle that wastes development time.


    Production Validation: Comprehensive Testing

    Isolated Environment Validation

    Test setup:

    # Create pristine environment
    mkdir /tmp/stremio-patch-validation
    cd /tmp/stremio-patch-validation
    git clone --branch v4.4.169 https://github.com/Stremio/stremio-shell.git .
    cp -r /path/to/debian .
    
    # Apply all patches
    export QUILT_PATCHES=debian/patches
    quilt push -a
    # Result: All 6 patches applied successfully
    
    # Test CMake build
    mkdir build && cd build
    cmake .. -DQT_DEFAULT_MAJOR_VERSION=5
    make -j$(nproc)
    # Result: 293KB binary with 100% system libraries
    
    # Test release.makefile
    cd .. && QT_DEFAULT_MAJOR_VERSION=5 make -f release.makefile
    # Result: Complete success including icon generation
    
    # Verify dependencies
    ldd build/stremio | head -5
    # Output:
    #   libQt5WebEngine.so.5 => /lib/x86_64-linux-gnu/libQt5WebEngine.so.5
    #   libQt5DBus.so.5 => /lib/x86_64-linux-gnu/libQt5DBus.so.5
    #   libcrypto.so.3 => /lib/x86_64-linux-gnu/libcrypto.so.3
    #   libmpv.so.2 => /lib/x86_64-linux-gnu/libmpv.so.2

    Verification results:

    • ✅ Binary builds successfully (293KB)
    • ✅ GUI loads and displays
    • ✅ Single-instance behavior works
    • ✅ Streaming server starts (port 11470 responds)
    • ✅ System library integration complete
    • ✅ No crashes or threading issues

    Runtime Validation

    Complete functionality test:

    # Launch application
    ./build/stremio 2>&1 | tee /tmp/stremio-runtime.log
    
    # Verify server startup (first 15 seconds)
    timeout 15s ./build/stremio 2>&1 | grep -E "(server|streaming|port)"
    # Output:
    #   hls executables located -> { ffmpeg: '/usr/bin/ffmpeg', ffsplit: null }
    #   Using app path -> /home/user/.stremio-server
    #   Enabling casting...
    #   EngineFS server started at http://127.0.0.1:11470
    
    # Test server endpoint
    curl -s http://127.0.0.1:11470 && echo "✓ Server responding"
    
    # Test single-instance behavior
    ./build/stremio &
    PID1=$!
    sleep 2
    ./build/stremio   # Should detect first instance and exit
    wait $PID1

    User Experience: Installation Simplified

    I wanted other Debian users to have the chance to install these packages built with the highest standards as soon as possible while the package is still being reviewed by Debian Developers. My solution was to create a repository and through GitHub Actions, pull the sources of the packages from salsa.debian.org, build them automatically, make a release and provide a Debian repository built with GitHub Pages, so Debian users will have 99% of availability to fetch them.

    The end result is a one-command installation for users:

    For Debian Trixie (13 – current stable)

    wget -qO - https://debian.vejeta.com/key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/stremio-debian.gpg
    echo "deb [signed-by=/usr/share/keyrings/stremio-debian.gpg] https://debian.vejeta.com trixie main non-free" | sudo tee /etc/apt/sources.list.d/stremio.list
    sudo apt update
    sudo apt install stremio stremio-server

    For Debian Sid / Kali Linux

    wget -qO - https://debian.vejeta.com/key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/stremio-debian.gpg
    echo "deb [signed-by=/usr/share/keyrings/stremio-debian.gpg] https://debian.vejeta.com sid main non-free" | sudo tee /etc/apt/sources.list.d/stremio.list
    sudo apt update
    sudo apt install stremio stremio-server

    For Ubuntu 24.04 LTS (Noble) – EXPERIMENTAL

    wget -qO - https://debian.vejeta.com/key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/stremio-debian.gpg
    echo "deb [signed-by=/usr/share/keyrings/stremio-debian.gpg] https://debian.vejeta.com noble main non-free" | sudo tee /etc/apt/sources.list.d/stremio.list
    sudo apt update
    sudo apt install stremio stremio-server

    Note: Ubuntu support is experimental with automated builds but limited manual testing. Community feedback welcome.


    Closing the Loop: Updating Documentation

    With a working solution deployed, I returned to where it all started—the documentation. I submitted a comprehensive pull request to update the original DEBIAN.md file I had contributed years earlier.

    The PR adds:

    • ✅ APT repository installation (new recommended method)
    • ✅ Complete dependency lists
    • ✅ Modern security practices (proper GPG key management)
    • ✅ Multi-distribution support (Debian + derivatives)
    • ✅ Maintained build instructions (preserved for developers)

    Community Impact

    Within hours of submitting the PR, I commented on 10+ existing GitHub issues where users had reported installation problems. The response was immediate and positive—users could finally install Stremio without compilation headaches.


    Technical Achievements Summary

    Packaging Excellence

    • Zero bundled dependencies: 100% Debian system libraries
    • FHS compliance: Proper /usr installation paths
    • License separation: GPL client (main) + proprietary server (non-free)
    • Policy compliance: Lintian-clean packaging
    • Independent versioning: Client v4.4.169 + Server v4.20.12

    Technical Solutions

    • QtWebEngine initialization fix: Single line prevents all QML crashes
    • CompatibleSingleApp: Custom thread-safe single-instance implementation
    • QProcess environment: Proper Node.js environment setup for streaming server
    • Dual build systems: CMake (293KB) and qmake (278KB) both working
    • System library integration: MPV, Qt5, OpenSSL, all QML modules

    Infrastructure

    • Multi-distribution builds: Trixie, Bookworm, Sid, Noble (experimental)
    • Automated CI/CD: GitHub Actions with matrix strategy
    • APT repository: GitHub Pages with global CDN
    • GPG signing: Cryptographically signed packages and metadata
    • Zero hosting costs: Unlimited bandwidth via GitHub
    • Download statistics: Built-in analytics via GitHub Releases

    Build Statistics

    • Binary size: 293KB optimized (vs 424KB debug)
    • Build time: ~10 minutes per distribution
    • Total distributions: 4 (3 Debian + 1 Ubuntu experimental)
    • Packages per release: 8 .deb files (4 distros × 2 packages)
    • Repository size: ~21 MB per release

    Looking Forward

    Immediate Goals

    Debian Submission Progress (ITP #943703):

    • [x] Source packages created following Debian Policy
    • [x] Lintian-clean packaging
    • [x] 100% system libraries
    • [x] FHS compliance
    • [x] Copyright file with complete licensing
    • [x] Watch files for upstream monitoring
    • [x] git-buildpackage workflow
    • [x] Packages hosted on Salsa
    • [x] ITP bug filed
    • [x] Preliminary Debian Developer review
    • [ ] Sponsorship obtained
    • [ ] Upload to Debian NEW queue

    Timeline: Submission planned for Q1 2025

    Professional Applications

    This work directly supports my goal of becoming an official Debian Package Maintainer. This could also serve as a guide for others to get experience with:

    • Packaging expertise: Modern Debian packaging workflows with complex applications
    • DevOps proficiency: CI/CD pipeline design and GitHub Actions automation
    • Problem-solving skills: Deep debugging (QtWebEngine, threading, environment issues)
    • Community engagement: Solving real user problems at scale
    • Infrastructure design: Scalable, cost-effective distribution systems
    • Documentation: Comprehensive technical writing for diverse audiences

    Future Evolution

    The architecture proved so successful that I’m considering replicating it for other packaging projects. The pattern of using GitHub infrastructure for APT repository hosting could benefit many projects struggling with distribution challenges.

    Potential applications:

    • Personal package repository for experimental Debian packages
    • Other media applications requiring complex Qt5/WebEngine setups
    • Cross-distribution packaging (Debian + Ubuntu + derivatives)

    Key Principles Reinforced

    This journey reinforced several fundamental principles:

    1. Documentation is Infrastructure

    Good documentation isn’t just text—it’s the foundation that enables user adoption and community growth. The original DEBIAN.md file evolved into a complete packaging and distribution solution.

    2. Packaging is Product Design

    How users install and maintain software is part of the user experience. Poor packaging creates friction; good packaging eliminates it. The difference between:

    • ❌ «Download, extract, install 15 dependencies, compile, copy files manually»
    • ✅ «apt install stremio»

    3. Modern Infrastructure Enables Scale

    By leveraging GitHub’s infrastructure (Actions, Pages, Releases), a single developer can provide enterprise-grade distribution infrastructure with zero operational overhead. This democratizes software distribution.

    4. Standards Enable Ecosystems

    Following Debian packaging standards meant the same packages work across multiple distributions (Debian, Ubuntu, Kali) and can integrate with the official Debian archive.

    5. Deep Technical Understanding Pays Off

    The critical fixes (QtWebEngine initialization, threading compatibility, environment variables) required deep understanding of:

    • Qt5 initialization order
    • QML engine threading model
    • QProcess environment inheritance
    • Node.js runtime requirements

    Surface-level knowledge wouldn’t have solved these problems.

    6. Proper Testing Prevents Rework

    The patch development lessons learned (70% time wasted on rework) demonstrate that upfront validation investment prevents significant downstream waste. Test against clean upstream early and often.

    7. Independent Versioning Respects Reality

    Using independent version numbers for stremio (4.4.169) and stremio-server (4.20.12) follows industry practice and accurately represents upstream development. Convenience versioning creates confusion.


    Acknowledgments

    • Stremio Team: For creating an excellent media center application
    • Debian Community: For packaging standards and infrastructure (Salsa)
    • GitHub: For free hosting, CI/CD, and unlimited bandwidth
    • Qt Project: For excellent cross-platform framework
    • Debian Developers (Arturo): For preliminary review and guidance on ITP #943703

    Technical Resources

    Source Repositories

    Upstream Projects

    Distribution Statistics

    • Repository Bandwidth: Unlimited (GitHub CDN)
    • Total Downloads: Tracked via GitHub Releases API
    • Uptime: 99.9%+ (GitHub SLA)
    • Build Success Rate: 100% (after fixes applied)

    Conclusion

    What started as a simple documentation contribution evolved into a comprehensive packaging and distribution solution. By combining traditional Debian packaging principles with modern CI/CD infrastructure, it’s possible to deliver professional-grade software distribution that scales globally.

    The journey from «how do I install this?» to «apt install stremio» represents more than technical progress—it’s about removing friction between great software and the people who want to use it.

    Sometimes the best solutions come full circle. Years after contributing installation documentation, I’ve returned to ensure that documentation describes a process that actually works reliably for everyone.

    The technical challenges (QtWebEngine initialization, threading compatibility, environment variables) required deep problem-solving and systematic debugging. The infrastructure challenges (multi-distribution builds, APT repository hosting, CI/CD automation) required modern DevOps practices and cloud-native thinking.

    But ultimately, this project is about enabling users. Every technical decision, every patch, every workflow optimization serves the goal of making Stremio accessible to Debian and Ubuntu users through a simple, reliable installation process.


    Part of ongoing contribution to become a Debian Package Maintainer

    If you found this article helpful, please consider:

    Last updated: October 30, 2025


    Appendix: Complete Command Reference

    Building from Source (Debian/Ubuntu)

    # Install build dependencies
    sudo apt install \
        git git-buildpackage pristine-tar \
        debhelper-compat cmake \
        qtbase5-dev qt5-qmake qt5-qmake-bin \
        qtdeclarative5-dev qtwebengine5-dev qttools5-dev \
        qml-module-qtwebchannel qml-module-qt-labs-platform \
        qml-module-qtwebengine qml-module-qtquick-dialogs \
        qml-module-qtquick-controls qml-module-qt-labs-settings \
        qml-module-qt-labs-folderlistmodel \
        libmpv-dev libssl-dev nodejs npm pkg-kde-tools \
        devscripts lintian dpkg-dev fakeroot librsvg2-bin
    
    # Clone repository
    git clone --recursive https://salsa.debian.org/mendezr/stremio.git
    cd stremio
    
    # Build with CMake
    mkdir build && cd build
    QT_DEFAULT_MAJOR_VERSION=5 cmake ..
    make -j$(nproc)
    
    # Or build with qmake
    QT_SELECT=5 qmake
    QT_SELECT=5 make -j$(nproc)
    
    # Or build package
    QT_DEFAULT_MAJOR_VERSION=5 dpkg-buildpackage -us -uc

    Testing Package Installation

    # Install package
    sudo dpkg -i ../stremio_*.deb
    
    # Fix dependencies if needed
    sudo apt install -f
    
    # Test binary
    stremio --version
    which stremio
    
    # Check dependencies
    ldd /usr/bin/stremio | grep -E "(libQt5|libmpv|libcrypto)"
    
    # Run application
    stremio

    Repository Management

    # Add GPG key
    wget -qO - https://debian.vejeta.com/key.gpg | \
        sudo gpg --dearmor -o /usr/share/keyrings/stremio-debian.gpg
    
    # Add repository (choose your distribution)
    echo "deb [signed-by=/usr/share/keyrings/stremio-debian.gpg] https://debian.vejeta.com trixie main non-free" | \
        sudo tee /etc/apt/sources.list.d/stremio.list
    
    # Update and install
    sudo apt update
    sudo apt install stremio stremio-server
    
    # Verify installation
    dpkg -L stremio
    systemctl --user status stremio-server  # If systemd service installed

    Debugging Runtime Issues

    # Run with debug output
    QT_DEBUG_PLUGINS=1 stremio
    
    # Run in headless mode (for testing)
    QT_QPA_PLATFORM=offscreen stremio
    
    # Disable WebEngine sandbox (for containers)
    QTWEBENGINE_DISABLE_SANDBOX=1 stremio
    
    # Check server process
    ps aux | grep server.js
    lsof -i :11470
    
    # Manual server test
    /usr/bin/node /usr/share/stremio/server.js
    
    # Test with gdb
    gdb --args stremio
    (gdb) run
    (gdb) bt  # If crash occurs

    End of Article


    Technical Depth: Production-grade implementation details
    Target Audience: Advanced developers, system administrators, Debian maintainers

  • Resucitando un Slimbook Pro (2019): Cuando la Persistencia Vence al Hardware «Muerto»

    Resucitando un Slimbook Pro (2019): Cuando la Persistencia Vence al Hardware «Muerto»

    Cómo resolver problemas gráficos complejos en Intel UHD Graphics 620 mediante diagnóstico sistemático y parámetros del kernel

    Hace dos meses, mi Slimbook Pro 2019 comenzó a mostrar síntomas que cualquier técnico habría diagnosticado como «hardware muerto»: pantalla interna parpadeando constantemente, sistema extremadamente lento, sesiones gráficas que se colgaban al arrancar. Después de cinco años de funcionamiento perfecto, parecía que había llegado el momento de reemplazarlo.

    Sin embargo, la persistencia y un enfoque sistemático de diagnóstico demostraron que incluso los problemas más graves pueden tener soluciones inesperadas. Este es el relato completo de cómo conseguí que un portátil «desahuciado» volviera a funcionar perfectamente, incluso ejecutando Cinnamon con efectos activados.

    Estado Inicial: Síntomas del Problema

    Hardware afectado:

    • Slimbook Pro (2019) con Intel Core i7 Comet Lake-U
    • Intel UHD Graphics 620 integrada
    • Sistema operativo: Debian GNU/Linux
    • Monitor externo: IProda PD182Kpn (portátil, ideal para complementar el portátil)

    Síntomas observados:

    • Pantalla interna parpadeando constantemente en negro (problema principal)
    • Sistema extremadamente lento, incluso con monitor externo conectado
    • Sesiones gráficas que fallan al arrancar o se cuelgan
    • Interfaz gráfica prácticamente inusable
    • Modo consola funcionando correctamente

    Contexto temporal: El portátil funcionó perfectamente desde 2019 hasta aproximadamente julio-agosto de 2025, cuando los problemas aparecieron súbitamente sin cambios significativos en hardware o software.

    Primera Fase: Diagnóstico y Descarte de Causas Obvias

    Análisis de Logs del Sistema

    El primer paso fue examinar los logs del kernel para identificar la causa raíz:

    sudo dmesg | grep -i "i915"
    

    Los logs revelaron información crítica sobre el controlador de Intel Graphics:

    i915 0000:00:02.0: [drm] Found cometlake/ult (device ID 9b41)
    WARNING: CPU: 0 PID: 176 at drivers/gpu/drm/i915/display/intel_pps.c:974 intel_pps_on_unlocked
    

    Hallazgo clave: Error en la secuencia de encendido del panel (Panel Power Sequence), indicando problemas en la gestión de energía de la pantalla interna.

    Verificación del Estado de las Pantallas

    cat /sys/class/drm/*/status
    # Resultado: 
    # disconnected
    # connected    # Pantalla interna (eDP-1) - causando problemas
    # disconnected  
    # connected    # Monitor externo HDMI-2
    

    Ambas pantallas eran detectadas correctamente por el kernel, pero la interna (eDP-1) estaba causando inestabilidad al sistema completo.

    Análisis de Aceleración Gráfica

    glxinfo | grep -E "(OpenGL renderer|direct rendering)"
    

    En este punto, el sistema mostró renderizado por software (llvmpipe), indicando que la aceleración hardware había fallado, explicando la extrema lentitud del sistema.

    Segunda Fase: Estrategias de Solución Sistemática

    Intento 1: Parámetros del Controlador i915

    Basándome en la investigación sobre problemas conocidos del Intel UHD Graphics 620 en Comet Lake, implementé los primeros parámetros correctivos en GRUB:

    sudo nano /etc/default/grub
    
    # Configuración inicial
    GRUB_CMDLINE_LINUX_DEFAULT="i915.enable_psr=0 i915.enable_rc6=0 i915.enable_guc=2 i915.enable_dc=0"
    
    sudo update-grub && sudo reboot
    

    Explicación de parámetros:

    • enable_psr=0: Desactiva Panel Self Refresh (causa común de parpadeo)
    • enable_rc6=0: Evita estados de bajo consumo problemáticos
    • enable_guc=2: Fuerza carga del firmware GuC/HuC
    • enable_dc=0: Desactiva Display C-states problemáticos en Comet Lake

    Resultado: Mejora marginal, pero el parpadeo de la pantalla interna persistía.

    Intento 2: Gestión de Controladores y Configuración de Xorg

    Cambié del controlador Intel tradicional al controlador modesetting más moderno:

    sudo nano /etc/X11/xorg.conf.d/20-intel.conf
    
    # Configuración
    Section "Device"
        Identifier "Intel Graphics"
        Driver "modesetting"
        Option "AccelMethod" "glamor"
        Option "TearFree" "true"
    EndSection
    

    Resultado: Sin mejoras significativas en la estabilidad.

    Intento 3: Gestión del Gestor de Pantalla

    Los problemas con SDDM llevaron a configurar scripts de inicialización para desactivar automáticamente la pantalla interna:

    sudo nano /usr/share/sddm/scripts/Xsetup
    
    #!/bin/bash
    sleep 3
    xrandr --output eDP-1 --off --output HDMI-2 --auto --primary
    

    Resultado: Mejoras temporales que no persistían entre reinicios, y la pantalla interna seguía parpadeando durante el arranque.

    Tercera Fase: El Breakthrough – Gestión de Energía PCIe y Desactivación a Nivel Kernel

    Identificación del Problema Real

    Un análisis más profundo de los logs reveló errores críticos que habían pasado desapercibidos:

    sudo tail -f /var/log/Xorg.0.log
    
    (WW) modeset(0): hotplug event: connector 106's link-state is BAD, tried resetting the current mode. You may be left with a black screen if this fails...
    

    Este mensaje aparecía repetidamente cada 1-2 segundos, indicando que el problema no era el renderizado gráfico sino la estabilidad de la conexión de los displays.

    La Solución Dual: PCIe ASPM + Desactivación de Pantalla Interna

    La solución final requirió dos enfoques complementarios:

    1. Desactivar la gestión de energía PCIe que causaba inestabilidad
    2. Desactivar completamente la pantalla interna a nivel de kernel para evitar que cause conflictos
    sudo nano /etc/default/grub
    
    # Configuración que solucionó el problema
    GRUB_CMDLINE_LINUX_DEFAULT="intel_iommu=igfx_off i915.enable_prs=0 i915.modeset=1 i915.enable_rc6=0 i915.enable_guc=2 i915.enable_dc=0 plymouth.enable=0 i915.enable_fbc=0 video=HDMI-2:1920x1080@60 video=eDP-1:d pcie_aspm=off"
    

    Parámetros clave explicados:

    Gestión de energía y estabilidad:

    • pcie_aspm=off: Crítico – Desactiva Active State Power Management de PCIe, resuelve errores «link-state BAD»
    • intel_iommu=igfx_off: Evita conflictos de mapeo de memoria con gráficos Intel
    • plymouth.enable=0: Desactiva pantalla de arranque problemática

    Configuración del controlador i915:

    • i915.enable_prs=0: Desactiva Panel Self Refresh (parpadeo)
    • i915.enable_dc=0: Desactiva Display C-states problemáticos en Comet Lake
    • i915.enable_rc6=0: Evita estados de bajo consumo problemáticos
    • i915.enable_guc=2: Fuerza carga del firmware GuC/HuC para mejor rendimiento
    • i915.modeset=1: Activa mode setting del kernel
    • i915.enable_fbc=0: Desactiva Frame Buffer Compression

    Configuración de pantallas:

    • video=HDMI-2:1920x1080@60: Fuerza resolución específica para el monitor externo
    • video=eDP-1:d: Desactiva completamente la pantalla interna a nivel de kernel (el parámetro :d significa «disabled»)

    ¿Por qué era Necesaria la Desactivación a Nivel Kernel?

    La pantalla interna parpadeante no solo era molesta visualmente, sino que causaba inestabilidad en todo el subsistema gráfico. Los intentos de desactivarla a nivel de Xorg (xrandr --output eDP-1 --off) llegaban demasiado tarde: el kernel ya había inicializado ambas pantallas y la interna ya había comenzado a causar problemas.

    El parámetro video=eDP-1:d instruye al kernel para que ignore completamente la pantalla interna durante el arranque, evitando que se inicialice y cause conflictos con el controlador de display.

    Cuarta Fase: Verificación del Éxito

    Resultados Inmediatos

    Tras el reinicio con la configuración final:

    # Verificación de aceleración hardware
    glxinfo | grep "OpenGL renderer"
    # Resultado: Mesa Intel(R) UHD Graphics (CML GT2)
    
    # Test de rendimiento
    vblank_mode=0 glxgears
    # Resultado: ~7500 FPS
    
    # Benchmark completo
    glmark2 --fullscreen
    # Puntuación: 590 (excelente para gráficos integrados)
    

    Cambios observados:

    • Pantalla interna completamente silenciosa – sin parpadeos desde el arranque
    • Arranque limpio – sin errores «link-state BAD» en los logs
    • Aceleración hardware restaurada – renderizado por hardware, no software
    • Sistema responsivo – rendimiento normal restaurado

    Resultados Finales

    Estado Actual del Sistema

    Hardware gráfico:

    • Aceleración hardware completamente funcional
    • Intel UHD Graphics 620 operando a pleno rendimiento
    • Monitor externo IProda PD182Kpn funcionando a 1920×1080@60Hz estable
    • Pantalla interna completamente desactivada – sin parpadeos

    Rendimiento del sistema:

    • Entorno de escritorio: Cinnamon con efectos activados
    • Rendimiento gráfico: 590 puntos en glmark2
    • Estabilidad: Sin errores «link-state BAD» en más de una semana de uso intensivo
    • Arranque limpio sin interferencias de la pantalla problemática

    Funcionalidades restauradas:

    • Sesiones gráficas estables
    • Reproducción de video fluida
    • Navegación web sin problemas
    • Capacidad para ejecutar entornos de escritorio modernos

    Validación de la Solución

    El sistema ahora supera las expectativas iniciales:

    # Test de texto 2D (relevante para trabajo de oficina)
    x11perf -aa10text
    # Resultado: 11M caracteres/segundo
    
    # Test de renderizado 3D básico
    glxgears (con vsync)
    # Resultado: 60 FPS estables sin caídas
    
    # Test sin vsync (rendimiento real)
    vblank_mode=0 glxgears  
    # Resultado: 7500+ FPS
    

    Lecciones Técnicas Aprendidas

    1. Los Síntomas Pueden Engañar

    Los síntomas (pantalla parpadeando, sistema lento) apuntaban a fallo de hardware gráfico. La realidad era un problema de gestión de energía PCIe que afectaba la estabilidad de las conexiones de display, más una pantalla interna defectuosa que interfería con todo el subsistema.

    2. La Importancia del Diagnóstico Profundo

    El error crítico «connector link-state BAD» solo era visible en logs específicos de Xorg, no en los logs generales del kernel. El diagnóstico superficial habría llevado a conclusiones erróneas.

    3. Soluciones Múltiples vs Solución Única

    El problema requería dos soluciones complementarias:

    • Estabilizar las conexiones PCIe (pcie_aspm=off)
    • Eliminar la fuente de conflictos (video=eDP-1:d)

    Una sola no era suficiente.

    4. Nivel de Intervención Importante

    Desactivar la pantalla a nivel de aplicación (xrandr) llegaba tarde. Era necesario intervenir a nivel de kernel para evitar que el problema se manifestara desde el inicio.

    Metodología de Diagnóstico Replicable

    Para técnicos que enfrenten problemas similares:

    Paso 1: Recolección de Información

    # Información del hardware
    lspci | grep VGA
    dmidecode -s system-manufacturer
    dmidecode -s bios-version
    
    # Estado de displays
    cat /sys/class/drm/*/status
    xrandr (si es accesible)
    
    # Logs críticos
    dmesg | grep -i "drm\|i915"
    journalctl -xe | grep -i "graphics\|display"
    tail -f /var/log/Xorg.0.log | grep -i "hotplug\|link-state"
    

    Paso 2: Identificación de Patrones

    • Parpadeo constante de pantalla = problema hardware específico de esa pantalla
    • Errores «link-state BAD» repetitivos = problema de gestión de energía PCIe
    • «llvmpipe» en renderizado = falta aceleración hardware (consecuencia)
    • Errores al inicializar sesión gráfica = inestabilidad del controlador de display

    Paso 3: Soluciones Incrementales

    1. Parámetros básicos del controlador i915
    2. Configuración de Xorg optimizada
    3. Gestión de energía PCIe (crítico)
    4. Desactivación de hardware problemático a nivel kernel
    5. Optimización específica por hardware

    Reflexiones sobre la Persistencia Técnica

    Este caso demuestra que el diagnóstico «hardware muerto» debe cuestionarse sistemáticamente. La tendencia a descartar hardware aparentemente fallido puede llevar a:

    • Pérdida económica innecesaria: Un portátil de €500 salvado vs €1000+ en reemplazo
    • Impacto ambiental: Evitar desecho prematuro de hardware funcional
    • Pérdida de datos y configuraciones: Mantener el entorno de trabajo existente

    Cuándo Persistir vs Cuándo Rendirse

    Indicadores para continuar el diagnóstico:

    • Hardware con historial de funcionamiento estable
    • Fallo súbito sin causa aparente
    • Funcionalidad parcial (consola funcionando)
    • Errores específicos en logs (no fallos aleatorios)
    • Un solo componente problemático identificable

    Indicadores para considerar reemplazo:

    • Múltiples componentes fallando simultáneamente
    • Errores de memoria física o CPU
    • Fallos intermitentes sin patrón reproducible
    • Costo de reparación > 60% del valor del equipo

    Configuración del Monitor Externo IProda PD182Kpn

    Una nota específica sobre el monitor portátil utilizado: el IProda PD182Kpn demostró ser un excelente compañero para el portátil reparado:

    Especificaciones relevantes:

    • Panel IPS de 18.5″ Full HD (1920×1080)
    • Conexión HDMI estable con el controlador Intel UHD 620
    • Alimentación via USB-C (compatible con puertos del Slimbook)
    • Perfil delgado ideal para trabajar en movilidad

    Configuración óptima:

    # Forzar resolución y frecuencia específicas
    xrandr --output HDMI-2 --mode 1920x1080 --rate 60
    
    # Configuración permanente en GRUB
    video=HDMI-2:1920x1080@60
    

    Este monitor demostró ser ideal para validar la solución, ya que requiere una señal HDMI completamente estable – cualquier inestabilidad en el controlador gráfico se manifestaría inmediatamente como parpadeos o desconexiones.

    Conclusión: El Valor de la Persistencia Técnica

    Lo que inicialmente parecía un fallo irreversible de hardware se resolvió completamente mediante:

    1. Diagnóstico sistemático en lugar de asunciones basadas en síntomas
    2. Investigación específica sobre el hardware exacto (Comet Lake + UHD 620)
    3. Identificación de componentes problemáticos específicos (pantalla interna)
    4. Soluciones a múltiples niveles (kernel + drivers + gestión de energía)
    5. Documentación detallada de cada intento para evitar repeticiones

    El resultado final supera las expectativas iniciales: un sistema que no solo funciona, sino que rinde mejor de lo esperado para gráficos integrados de 2019. La capacidad de ejecutar Cinnamon con efectos activados demuestra que el hardware tenía potencial que estaba siendo bloqueado por configuraciones subóptimas y un componente específico defectuoso.

    Para cualquier técnico enfrentando problemas similares, el mensaje clave es: antes de declarar hardware muerto, agota las posibilidades de configuración y aísla componentes problemáticos. Los sistemas modernos tienen tantas capas de abstracción (kernel, drivers, gestión de energía, protocolos de display) que los problemas aparentemente de hardware a menudo tienen soluciones de software, especialmente cuando se puede identificar y desactivar el componente específico que causa conflictos.

    La persistencia técnica, combinada con metodología sistemática, puede salvar hardware que de otra manera terminaría prematuramente en el desecho. En un mundo donde la sostenibilidad tecnológica es cada vez más importante, estas victorias tienen valor tanto económico como ambiental.

    El Slimbook Pro 2019 ha vuelto a la vida, demostrando que a veces lo que parece el final es solo un problema esperando la solución correcta – y la determinación para encontrarla.

  • Nueva edición del Hackmeeting en A Corunha

    En éste portal nos hacemos eco de las llamadas a la participación:

    «Hackers, hacktivistas, nerds, lurkers, hobbistas de la tecnologia, geeks y otras «meigas» se vuelven a poner manos a la tecla para, bit a bit y ping a ping, implementar el XII Hackmeeting. Un encuentro que, durante un fin de semana autogestionado y libre, y entrecruzando los hilos de lo social, lo tecnológico y lo político, construye una nueva forma de crear, de relacionarse, de disfrutar compartiendo y aprender enseñando. Estos tres días de autogestión, autoorganización, circulación libre de saberes, hacktivismo, ciberactivismo, ética hacker, ciclohacking, apropiación de los medios de producción, media libre, software libre, hardware libre, autonomía, p2p, guifi.net y redes libres, entre otras cosas tendrán lugar en el CSO Palavea de A Coruña, del 21 al 23 de octubre. ¡Ven y comparte, el hackmeeting también eres tú!»

    Este año vuelve a entrarnos las ganas de juntarnos en torno a lo que nos motiva: el hacktivismo, el ciberespacio, la cultura del software y el hardware libres… Un fin de semana autogestionado en el que compartir experiencias y proyectos tecnopolíticos.

    El HackMeeting se compone de una serie de nodos (talleres, charlas) autónomos y entrelazados. Todas las actividades en un Hackmeeting son llevadas a cabo por personas voluntarias. Cualquiera puede proponer o presentar un nodo. Esta llamada a la participación pretende animar a proponer y presentar un nodo a quien tenga algo que quiera compartir este Hackmeeting.

    No hay una idea preconcebida de qué va a ser este hackmeeting. Hacking y hacktivismo en un sentido amplio: hacking de máquinas y protocolos pero también de códigos sociales y de la manera de entender y usar la tecnología. Ven y comparte tus hacks (informáticos o no) de mentes e ideas víricas. Copyfight, redes distribuidas, hardware libre, inventos o música, debates o talleres…

    Puedes ver una lista de los nodos propuestos este año en el siguiente enlace:


    http://sindominio.net/hackmeeting/index.php?title=2011/Nodos

    Si vas este año, te invitamos a que nos cuentes la experiencia.

  • Nueva generación de sistemas de ficheros para Linux: NiLFS y exofs

    Sistemas de ficheros basados en logs

    NiLFS(2) es otro sistema de ficheros con la caracteristicas de realizar «instantáneas» (snapshots) de los datos. Otros sistemas de ficheros que incluyen snapshots son ZFS, LFS o Ext3cow.

     

    Es un sistema de ficheros ideal para discos de estado solido (SSD), ya que se minimizan las escrituras y borrados, ampliando el tiempo de vida de estas memorias.

     

    John Ousterhout y Fred Dougles ya propusieron este tipo de sistemas en 1988 y fué implementado en el sistema operativo Sprite en 1992.  Un sistema de ficheros basado en logs concibe el sistema como un registro (log) circular en el que los datos y metadatos se escriben por la parte delantera y el espacio libre se va recuperando por la cola.  Con este sistema los datos pueden aparecer 2 más veces en el log, pero como el log va avanzando cronologicamente, sólo los datos más recientes se toman como datos activos.

     

    La demostración de NiLFS(2)

    se hizo sobre el kernel 2.6.27 de linux y la versión 2.6.30-rc1 ya incluye NiLFS(2) en la rama principal.

     

     

     

    Sistemas de almacenamiento basados en objetos

     

    En los sistemas de almacenamiento tradicionales se usan bloques para guardar los datos, y los metadatos ocupan parte de estos bloques.  En un sistema de almacenamiento basado en objetos, en lugar de trabajar con bloques de tamaño fijo se trabajan con objetos de tamaño variable y sus metadatos asociados.

     

    exofs fue creado en IBM por Avnishay Traeger y fué llamado OSD file system (osdfs). Actualmente, Panasas, continúa el proyecto y lo ha renombrado a exofs.

     

     

    Para más información sobre como instalar y usar estos sistemas de ficheros, visitar la referencia.

     

    Referencia:

    NiLFS(2) and exofs

     

  • XtreemOS 2.0 publicado

    XtreemOS 2.0 ha sido publicado. Uno de los componentes principales es el sistema de ficheros distribuido XtreemFS.

    «XtreemOS nos brinda nuevas oportunidades a la computación distribuida, tales como una gestión sencilla de los procesos y su monitorización»

     

    Tal como comentan en http://lwn.net/Articles/362285/ sería interesante comparar XtreemOS y XtreemFS con otras soluciones, como

    por ejemplo Xcpu, el cual basandose en protocolo 9p de Plan9 tiene una finalidad similar.

    XCPU: a new, 9p-based, process management system for clusters and grids

    http://xcpu.org/

     

     

    Otros enlaces de interés:

    http://es.wikipedia.org/wiki/XtreemOS

  • ACM (Association for Computing Machinery) publica serie de artículos sobre el kernel Linux

    Se incluyen 12 articulos sobre desarrollos experimentales que pueden ser incluidos en el futuro en el kernel linux.

    Puedes encontrar los articulos en cuestión aquí:

    http://portal.acm.org/toc.cfm?id=1400097

    * Minding the gap: R&D in the Linux kernel
            by Muli Ben-Yehuda, Eric Van Hensbergen, Marc Fiuczynski
    * Introducing technology into the Linux kernel: a case study
            by Paul E. McKenney, Jonathan Walpole
    * Extending futex for kernel to user notification
            by Helge Bahmann, Konrad Froitzheim
    * Plan 9 authentication in Linux
            by Ashwin Ganti
    * Towards achieving fairness in the Linux scheduler
            by Chee Siang Wong, Ian Tan, Rosalind Deena Kumari, Fun Wey
    * I/O resource management through system call scheduling
            by Silviu S. Craciunas, Christoph M. Kirsch, Harald Röck
    * PipesFS: fast Linux I/O in the unix tradition
            by Willem de Bruijn, Herbert Bos
    * CUBIC: a new TCP-friendly high-speed TCP variant
            by Sangtae Ha, Injong Rhee, Lisong Xu
    * On the design of a new Linux readahead framework
            by WU Fengguang, XI Hongsheng, XU Chenfeng
    * Practical techniques for purging deleted data using liveness information
            by David Boutcher, Abhishek Chandra
    * virtio: towards a de-facto standard for virtual I/O devices
            by Rusty Russell
    * Virtual servers and checkpoint/restart in mainstream Linux
            by Sukadev Bhattiprolu, Eric W. Biederman, Serge Hallyn, Daniel Lezcano
Creative Commons License
Except where otherwise noted, the content on this site is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.