Tutorial
Installation
It's recommended to install Mahoraga with uv >=0.9.0:
uv tool install -U mahoraga
Server Configuration
Before starting Mahoraga, you need to initialize a directory (for example ~/.mahoraga) to hold its configuration and data:
uvx mahoraga new ~/.mahoraga
uvx pyvim ~/.mahoraga/mahoraga.toml
Note
Running uvx without uv tool install will result in a full installation every time you run the tool. See uv tool documentation for details.
Server Deployment
Start the server directly to check if your configuration is correct:
cd ~/.mahoraga
uvx mahoraga run
~/.mahoraga/log/mahoraga.log. If the server started successfully, you can configure your clients and try fetching some packages from Mahoraga. Then if everything goes well, press Ctrl+C to stop the server, and start it again in the background: uvx mahoraga run &>/dev/null &
uvw tool run mahoraga run
For better performance, you can set up a non-Python server in front of Mahoraga. Packages cached on disk can be served within that server, so that subsequent requests won't go to Mahoraga again. We provide configuration files for Nginx and Caddy out-of-the-box.
You can find the following Nginx configuration files in ~/.mahoraga/nginx:
nginx.conf: Top-level configuration file for direct use.mahoraga.conf: A snippet intended to be included in thehttpblock of another file.
Note
For Linux and macOS, Nginx is available in conda-forge and can be installed by Pixi:
pixi global install nginx
To start the Nginx server, run nginx -c ~/.mahoraga/nginx/nginx.conf.
You can find the Caddy configuration file at ~/.mahoraga/Caddyfile. As the name suggests, it can be used as the top-level configuration file directly. In addition, it's also a valid snippet when imported to the root of another Caddyfile, since it doesn't contain a global options block.
To start the Caddy server, run cd ~/.mahoraga && caddy run.
When configuring the clients, make sure they don't communicate with Mahoraga directly, but through Nginx or Caddy.
Client Configuration
Note
Mahoraga serves on http://127.0.0.1:3450 by default. Replace it with the actual URL exposed to your clients.
uv
To get started on your client machine, install uv >=0.9.10 if you haven't got it elsewhere:
curl -LsSf http://127.0.0.1:3450/uv/uv-installer.sh |
env UV_DOWNLOAD_URL="http://127.0.0.1:3450/uv" sh
$Env:UV_DOWNLOAD_URL = "http://127.0.0.1:3450/uv"
irm http://127.0.0.1:3450/uv/uv-installer.ps1 | iex
When upgrading uv installed in this way, run the same command again. We don't support uv self update at this moment.
Run the following script to let Mahoraga take over the requests from uv, Pixi and other Rattler-based tools. You can also download, view and edit the script before executing it.
UV_PYTHON_INSTALL_MIRROR=http://127.0.0.1:3450/python-build-standalone \
uv run --default-index http://127.0.0.1:3450/pypi/simple \
http://127.0.0.1:3450/static/client_config.py \
http://127.0.0.1:3450
$Env:UV_PYTHON_INSTALL_MIRROR = "http://127.0.0.1:3450/python-build-standalone"
uv run --default-index http://127.0.0.1:3450/pypi/simple `
http://127.0.0.1:3450/static/client_config.py `
http://127.0.0.1:3450
Upgrading or downgrading uv to a specific version is not directly supported, however a small shell trick can work:
alias uv='uvx uv@0.9.10'
function uv {
uvx 'uv@0.9.10' @args
}
Pixi
Note
This section is about Pixi installation. If you already have Pixi >=0.43.1 installed, you can skip it since Pixi configuration was done in the previous section.
There is no mirror for the standalone installer of Pixi as of now. Instead, run the following script to install Pixi when you have uv installed and configured:
uv run http://127.0.0.1:3450/static/get_pixi.py
PIXI_HOME , replacing any existed version, and prepend $PIXI_HOME/bin to your PATH. To specify a version, pass it as CLI argument: get_pixi.py '0.43.1' # Exact version
get_pixi.py '0.43.*' # Latest revision of a specific minor version
get_pixi.py '>=0.43.1,<1' # Version range
PIXI_NO_PATH_UPDATE if present. Pyodide
Note
Mirror configuration requires Pyodide version 0.28.0 or later.
Pyodide Python distribution, wheels and JavaScript/WebAssembly runtime are all available in Mahoraga. To enable them, add the following line to your mahoraga.toml:
[cors]
allow-origins = [
"*",
]
mahoraga.conf or Caddyfile like this: # if ($http_origin) {
# add_header Access-Control-Allow-Origin *;
# }
# header @mahoraga-has-origin Access-Control-Allow-Origin *
The frontend configuration depends on the library you directly use:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="http://127.0.0.1:3450/pyodide/v0.29.4/full/pyodide.js"></script>
</head>
<body>
<script type="text/javascript">
async function main() {
let pyodide = await loadPyodide();
await pyodide.loadPackage("micropip");
// Prefer Pyodide-maintained wheels over PyPI ones
// If this is not desired, remove the following lines
pyodide.runPython(`
import micropip
class _Transaction(micropip.transaction.Transaction):
def __post_init__(self):
super().__post_init__()
self.search_pyodide_lock_first = True
micropip.package_manager.Transaction = _Transaction
`);
const micropip = pyodide.pyimport("micropip");
micropip.set_index_urls("http://127.0.0.1:3450/pypi/simple/{package_name}/?micropip=1");
await micropip.install(["your_package"]);
pyodide.runPython(`# Your Python code here`);
}
main();
</script>
</body>
</html>
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="module" src="http://127.0.0.1:3450/npm/@pyscript/core@0/dist/core.js"></script>
<link rel="stylesheet" href="http://127.0.0.1:3450/npm/@pyscript/core@0/dist/core.css">
</head>
<body>
<script type="py" config='{
"index_urls": ["http://127.0.0.1:3450/pypi/simple/{package_name}/?micropip=1"],
"interpreter": "http://127.0.0.1:3450/pyodide/v0.29.4/full/pyodide.mjs",
"packages": ["your_package"]
}'># Your Python code here</script>
</body>
</html>
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<link rel="stylesheet" href="http://127.0.0.1:3450/npm/@stlite/browser@1/build/stlite.css">
</head>
<body>
<div id="root"></div>
<script type="module">
import { mount } from "http://127.0.0.1:3450/npm/@stlite/browser@1/build/stlite.js";
mount(
{
pyodideUrl: "http://127.0.0.1:3450/pyodide/v0.29.4/full/pyodide.js",
requirements: [
"http://127.0.0.1:3450/pypi/packages/py3/b/blinker/blinker-1.9.0-py3-none-any.whl",
"http://127.0.0.1:3450/pypi/packages/py3/i/itsdangerous/itsdangerous-2.2.0-py3-none-any.whl",
"http://127.0.0.1:3450/pypi/packages/py3/p/python-multipart/python_multipart-0.0.32-py3-none-any.whl",
"http://127.0.0.1:3450/pypi/packages/py3/t/tenacity/tenacity-9.1.4-py3-none-any.whl",
],
entrypoint: "your_app.py",
files: {
"your_app.py": `# Your Python code here`,
},
},
document.getElementById("root"),
);
</script>
</body>
</html>
pymanager
The next generation of the official Python installer for Windows, pymanager, can be downloaded from Mahoraga:
curl -O http://127.0.0.1:3450/python/pymanager/python-manager-26.3.msix
curl -O http://127.0.0.1:3450/python/pymanager/python-manager-26.3.msi
Note
Support for the command pymanager install hasn't been implemented in Mahoraga yet.