/
/
/
Ansible role that deployes services on my runner machine
1---
2# Runner Services - LiveKit WebRTC Conferencing Stack
3# livekit-server (SFU) + LiveKit Meet (browser frontend + token generator)
4
5- name: Create LiveKit configuration directory structure
6 file:
7 path: "{{ item }}"
8 state: directory
9 owner: "{{ runner_user }}"
10 group: "{{ runner_group }}"
11 mode: '2775'
12 loop:
13 - "{{ livekit_config_dir }}"
14 - "{{ livekit_data_dir }}"
15
16- name: Create LiveKit assets directory
17 file:
18 path: "{{ livekit_config_dir }}/assets"
19 state: directory
20 owner: "{{ runner_user }}"
21 group: "{{ runner_group }}"
22 mode: '2775'
23 when: livekit_agent_avatar_enabled
24
25# Bind-mounted into Meet's public/ rather than baked into the image, so
26# replacing the picture is a re-run rather than a rebuild.
27- name: Install session agent avatar
28 copy:
29 src: "{{ livekit_agent_avatar_src }}"
30 dest: "{{ livekit_config_dir }}/assets/{{ livekit_agent_avatar_filename }}"
31 owner: "{{ runner_user }}"
32 group: "{{ runner_group }}"
33 mode: '0664'
34 when: livekit_agent_avatar_enabled
35 notify: restart livekit
36
37- name: Create LiveKit server configuration
38 template:
39 src: livekit-config.yaml.j2
40 dest: "{{ livekit_config_dir }}/livekit.yaml"
41 owner: "{{ runner_user }}"
42 group: "{{ runner_group }}"
43 mode: '0640'
44 notify: restart livekit
45
46- name: Create LiveKit Meet environment file
47 template:
48 src: livekit.env.j2
49 dest: "{{ livekit_config_dir }}/.env"
50 owner: "{{ runner_user }}"
51 group: "{{ runner_group }}"
52 mode: '0640'
53 notify: restart livekit
54
55- name: Create LiveKit Meet Dockerfile
56 template:
57 src: livekit-meet-Dockerfile.j2
58 dest: "{{ livekit_config_dir }}/Dockerfile.meet"
59 owner: "{{ runner_user }}"
60 group: "{{ runner_group }}"
61 mode: '0664'
62 register: livekit_meet_dockerfile
63 notify: restart livekit
64
65- name: Create LiveKit Docker Compose file
66 template:
67 src: livekit-compose.yml.j2
68 dest: "{{ livekit_config_dir }}/docker-compose.yml"
69 owner: "{{ runner_user }}"
70 group: "{{ runner_group }}"
71 mode: '0664'
72 notify: restart livekit
73
74# The Meet image is built from source. Rebuild only when the Dockerfile
75# changes or the image is absent, so repeat runs stay idempotent.
76- name: Check if LiveKit Meet image exists
77 community.docker.docker_image_info:
78 name: "livekit-meet:{{ livekit_meet_repo_version }}"
79 register: livekit_meet_image_info
80 check_mode: no
81
82- name: Build LiveKit Meet image
83 community.docker.docker_compose_v2:
84 project_src: "{{ livekit_config_dir }}"
85 build: always
86 state: present
87 services:
88 - livekit-meet
89 when: >
90 livekit_meet_dockerfile is changed
91 or (livekit_meet_image_info.images | default([]) | length == 0)
92 check_mode: no
93
94- name: Start LiveKit stack
95 community.docker.docker_compose_v2:
96 project_src: "{{ livekit_config_dir }}"
97 state: present
98 register: livekit_start_result
99 check_mode: no
100
101- name: Wait for LiveKit server to be healthy
102 uri:
103 url: "http://localhost:{{ livekit_port }}/"
104 method: GET
105 status_code: [200, 404]
106 register: livekit_health
107 until: livekit_health.status in [200, 404]
108 retries: 20
109 delay: 5
110 when: livekit_start_result is changed
111 check_mode: no
112
113- name: Wait for LiveKit Meet to be healthy
114 uri:
115 url: "http://localhost:{{ livekit_meet_port }}/"
116 method: GET
117 status_code: [200, 302]
118 register: livekit_meet_health
119 until: livekit_meet_health.status in [200, 302]
120 retries: 30
121 delay: 10
122 when: livekit_start_result is changed
123 check_mode: no
124
125- name: Display LiveKit deployment summary
126 debug:
127 msg: |
128 LiveKit Conferencing Stack Deployment:
129 - Status: {{ 'Started' if livekit_start_result is changed else 'Already running' }}
130
131 LiveKit Server (SFU):
132 - Signaling / API: http://{{ ansible_default_ipv4.address }}:{{ livekit_port }}
133 - WebSocket URL: {{ livekit_public_ws_url }}
134 - WebRTC TCP: {{ livekit_tcp_port }}
135 - WebRTC UDP (mux): {{ livekit_udp_port }}
136 - Network mode: host (required for WebRTC ICE)
137 - Redis: not deployed (single-node, in-memory room state)
138
139 LiveKit Meet (Browser UI + Token Generator):
140 - Web UI: http://{{ ansible_default_ipv4.address }}:{{ livekit_meet_port }}
141 - Token endpoint: /api/connection-details
142 - Built from: {{ livekit_meet_repo_url }}@{{ livekit_meet_repo_version }}
143
144 Directories:
145 - Configuration: {{ livekit_config_dir }}
146 - Data: {{ livekit_data_dir }}
147
148 NOTE: Meet's token endpoint is unauthenticated by default. Anyone who can
149 reach {{ livekit_domain }}:{{ livekit_meet_port }} on the LAN can join or create any room.
150
151 Verify media flow: open the Web UI in two browser tabs, join the same
152 room, and confirm audio/video connect in both directions.
153