Français [English]

My Linux Development Environment for Flutter Android Apps

Why I use Flutter to create Android apps

The official tool to create Android applications is Android Studio, which is available on Linux. This tool is an IDE based on IntelliJ Idea. But what if I want to use another IDE and not rely on one that needs a lot of resources to work (according to the documentation at least 8GB RAM required and 32GB recommended!)?

I am a Neovim user and I find it great software. It’s by default lightweight, highly customizable, and can be turned as a powerful IDE with all the features you could expect (LSP, formatters, debuggers…) thanks to plugins. Yet don’t try to directly replace Android Studio with Neovim. The former, while requiring a lot of resource to work, is still the best tool to manage and integrate all the components needed to run Android applications (that is, XML files for UI resources, the Java/Kotlin code, device emulation, Gradle…).

Flutter is a framework that allows you to build cross-platform applications (for Android, iOS, Windows, Linux…) thanks to an single programming language called Dart. What I love with Flutter is that you can tell how the UI of your app works by just looking at the Dart code. For Android projects written in Java/Kotlin, I find it more difficult to figure out the UI layout just by looking at the code, especially because it relies on both XML files and Java/Kotlin code (actually a new toolkit called Jetpack Compose allows in the same way as Dart to have a declarative UI that you can guess just by reading Kotlin code. But the ecosystem of that toolkit is still very tied to Android Studio). The main reason I’m using Flutter is because it’s very easy to code Flutter apps in Neovim thanks to the flutter-tools.nvim plugin.

Why I don’t want to install Flutter on my Linux environment

If you install and use Flutter on your machine, multiple new files and directories will be created on your home folder:

$HOME
├── .cache
├── .config
├── .dart-tool
├── .dartServer
├── .flutter-devtool
├── .local
├── .pki
├── .pub-cache
├── .ssh
├── Desktop
├── Documents
├── Downloads
├── Music
├── Pictures
├── Public
├── Templates
├── Videos
├── .bash_profile
├── .bashrc
└── .flutter

As above you can see 5 Flutter and Dart files and directories in your $HOME: .dart-tool, .dartServer, .flutter-devtool, .pub-cache and .flutter. This leads to a disorganized $HOME folder, especially when the majority of programs follows the “XDG Base Directory” specification which makes storing all of this kind of files and folders more organized. If you don’t know about that specification, the goal is to keep configuration and cache files of programs inside either ~/.config, ~/.cache, ~/.local/share or ~/.local/state, so that the home directory stays clean:

$HOME
├── .cache
├── .config
├── .local
├── .pki
├── .ssh
├── Desktop
├── Documents
├── Downloads
├── Music
├── Pictures
├── Public
├── Templates
├── Videos
├── .bash_profile
└── .bashrc

Flutter developers know they are not following the XDG specification:

You can find GitHub users complaining about this since 2020, and as of now (beginning of 2026 when I’m writing this), the issue is still there. The devs will in a not too distant future give users the ability to specify through an environment variable a common directory for all the above Flutter and Dart files and folders (that is, for instance keep all of them inside ~/.local/share/dart. This is great, but it does not follow to the letter the XDG specification).

So instead of waiting 6 years for an issue to be fixed, I decided to deploy Flutter in a VM so that my home directory stays clean. And to be honest, I don’t really want to run in my Linux distro a program that enables telemetry by default (“opt-out”). Yes Flutter is free software, but this does not inspire confidence. So let’s isolate Flutter!

Installing a VM with Flutter in it

Why a VM

So the main goal is to isolate Flutter so that it never interacts with my home directory. There are multiple ways to isolate processes in Linux, and here I will use virtual machines. You might ask why not OCI containers like Docker. The reason is that we need a persistent environment because we’ll install many tools (see below) used to build Android apps. I’m aware you can use Docker volumes to persist data, but here using a VM seems to me the cleanest way to create our Flutter dev environment.

You might also know how to use a LXC container, which is more lightweight than virtual machines and which can be great for what we want to do. If you know how to use this and want a lighter solution, go for it. Here I will focus on what’s the most popular, that is, virtual machines.

Creating the VM with virt-install

To run virtual machines in Linux, the best tool according to me is libvirt. I will install the VM with virt-install and manage it with virsh, but you might find it better to use a graphical UI. In that case I highly recommend virt-manager. I will not describe how to install all these tools, please refer to the official documentation as the installation might depend on your own Linux distro. You can still look at the great Arch Linux wiki.

Please choose the Linux distro you like for the VM. Neither Flutter nor Android official doc recommend using a specific distro. They do reference apt-get (and also yum for Android doc) though 1 2. Also the official documentation to build AOSP (which is not the goal here) uses Ubuntu 18.04 or later 3. So the safe choice here would be to use Ubuntu LTS. As for me I will use Arch Linux because I’m used to it and because I want to install the latest version of Neovim.

Download a cloud image of the distro you chose for the VM, with cloud-init installed (not mandatory but highly recommended to simplify the process of setting up the VM).

mkdir -p ~/Documents/Flutter/dev-vm
cd ~/Documents/Flutter/dev-vm
# For Arch, go check
# https://gitlab.archlinux.org/archlinux/arch-boxes/-/packages to get the
# up-to-date URL below
wget "https://gitlab.archlinux.org/archlinux/arch-boxes/-/package_files/11243/download"

We check the integrity of the image we’ve just downloaded. For Arch, check again the above GitLab link so to retrieve:

To verify the checksum:

sha256sum -c Arch-Linux-x86_64-cloudimg-20260301.495047.qcow2.SHA256

To verify the signature, the public key used to sign the files is here. Run:

gpg --import arch-key.asc
gpg --verify Arch-Linux-x86_64-cloudimg-20260301.495047.qcow2.sig
gpg --verify Arch-Linux-x86_64-cloudimg-20260301.495047.qcow2.SHA256.sig

Create a SSH key that will be used to connect to the VM:

ssh-keygen -f ~/.ssh/id_ed25519_flutter -C host
# Show the public key. We'll use it later
cat ~/.ssh/id_ed25519_flutter.pub

Create a user-data.yaml file that contains the following. The idea here is to create two users, one name arch as a system administrator of the VM, and one named flutter used to run Flutter commands. We also install dependencies for Flutter 1 and for the Android tools used to build apps. Finally we append a line to /etc/fstab to mount in the VM a shared storage so that we can retrieve our Flutter projects inside the VM.

#cloud-config
users:
  - name: flutter
    ssh_authorized_keys:
      # Put the above SSH public key
      - ssh-ed25519 ... host
  - name: arch
    sudo: 'ALL=(ALL:ALL) NOPASSWD: ALL'
    ssh_authorized_keys:
      # Put the above SSH public key
      - ssh-ed25519 ... host

packages:
  # In Arch, curl and xz are already installed
  #- curl
  - git
  - unzip
  #- xz
  - zip
  - glu
  - which
  - wget
  - jdk17-openjdk
  # Neovim and some useful tools
  - neovim
  - less
  - gcc
  - fd

write_files:
  - path: /etc/fstab
    append: true
    defer: true
    content: |-
      shared_mount /home/flutter/my-project virtiofs defaults 0 0

We install the VM with the following command. Replace $HOME/Documents/Flutter/my-projects with the path to your Flutter projects.

virt-install --connect qemu:///system \
  --name flutter-dev \
  --network network=default \
  --memory 8192 \
  --vcpus 4 \
  --osinfo archlinux \
  --import \
  --noreboot \
  --cloud-init user-data="$HOME/Documents/Flutter/dev-vm/user-data.yaml" \
  --disk pool=default,size=20,backing_store="$HOME/Documents/Flutter/dev-vm/Arch-Linux-x86_64-cloudimg-20260301.495047.qcow2" \
  --memorybacking source.type=memfd,access.mode=shared \
  --filesystem source="$HOME/Documents/Flutter/my-projects",target=shared_mount,driver.type=virtiofs

The installation takes some time. You can tell it’s done once the VM shows [ OK ] Reached target Cloud-init target.. Check cloud-init has installed everything. Open another terminal, log in with arch, update the VM and shut it down:

# We retrieve the local IP address of the VM with:
virsh --connect qemu:///system domifaddr flutter-dev
ssh -i ~/.ssh/id_ed25519_flutter arch@192.168.122.123
# Inside the VM
sudo pacman -Syu
sudo poweroff

Flutter and Android command line tools installation

Start the VM and log in as flutter:

virsh --connect qemu:///system start flutter-dev
ssh -i ~/.ssh/id_ed25519_flutter flutter@192.168.122.123

We install Flutter 1:

mkdir ~/develop
cd ~/develop
# Check Flutter's website to get the up-to-date URL
wget "https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.41.4-stable.tar.xz"
tar -xf flutter_linux_3.41.4-stable.tar.xz -C .
echo 'export PATH="$HOME/develop/flutter/bin:$PATH"' >> ~/.bashrc
# Log out then log in, then check the installation worked
flutter --version
flutter --disable-analytics
dart --version

Then install Android command line tools, used to build the apps 4.

Note that the tools are installed thanks to an archive that contains these tools inside the cmdline-tools/bin folder. This causes some tools not working properly because they expect the path cmdline-tools/latest/bin instead. To fix this, we first install the command line tools with the archive, then reinstall these with sdkmanager that will fix the path, and finally remove the tools installed with the archive.

cd ~/develop
# Below link comes from "https://developer.android.com/studio", secton "Command
# line tools only". Check the URL is up-to-date.
wget "https://dl.google.com/android/repository/commandlinetools-linux-14742923_latest.zip"
unzip commandlinetools-linux-14742923_latest.zip -d ~/develop/temp-android-sdk
mkdir -p ~/Android/Sdk
~/develop/temp-android-sdk/cmdline-tools/bin/sdkmanager --sdk_root=$HOME/Android/Sdk/ "cmdline-tools;latest"
rm -rf ~/develop/temp-android-sdk
echo 'export PATH="$HOME/Android/Sdk/cmdline-tools/latest/bin:$PATH"' >> ~/.bashrc
# Log out then log in
sdkmanager "platforms;android-36.1" "build-tools;36.1.0" "platform-tools"
# Note that Flutter expects other tools such as cmake and NDK. It's fine
# because the former will automatically install the missing components when
# running `flutter build apk`

# Check Flutter can find the Android SDK tools
flutter doctor
# Accept Android licenses
flutter doctor --android-licenses

Neovim

Install your own Neovim configuration.

If you have none, you can for instance install Lazyvim (Neovim distribution) and add the Flutter plugin:

git clone https://github.com/LazyVim/starter ~/.config/nvim
rm -rf ~/.config/nvim/.git
cat <<EOF > ~/.config/nvim/lua/plugins/flutter.lua
return {
  {
    "nvim-flutter/flutter-tools.nvim",
    lazy = false,
    dependencies = { "nvim-lua/plenary.nvim" },
    config = true,
  },
}
EOF

Useful commands to manage the VM

# To start the VM
virsh --connect qemu:///system start flutter-dev
# To stop the VM (yes you need to use `destroy`)
virsh --connect qemu:///system destroy flutter-dev

# To log in
virsh --connect qemu:///system domifaddr flutter-dev
ssh -i ~/.ssh/id_ed25519_flutter flutter@192.168.122.123

In order to avoid writing --connect qemu:///system every time, you can use the environment variable LIBVIRT_DEFAULT_URI 5.

Or use virt-manager if you want a GUI to manage the VM.

How to test your Flutter apps on web platforms

You need SSH port forwarding:

ssh -i ~/.ssh/id_ed25519_flutter -L 8080:localhost:8080 flutter@192.168.122.123
# Inside the VM
cd /path/to/flutter/project
flutter run -d web-server --web-port 8080

Drawbacks of my development environment

Despite all of these drawbacks, my home directory stays clean!


  1. https://docs.flutter.dev/install/manual ↩︎ ↩︎ ↩︎

  2. https://developer.android.com/studio/install#linux ↩︎

  3. https://source.android.com/docs/setup/start/requirements ↩︎

  4. https://docs.flutter.dev/platform-integration/android/setup ↩︎

  5. https://wiki.archlinux.org/title/Libvirt#Management ↩︎

* Next >