diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000000000000000000000000000000000000..b90fc2805bbe86770f822165f29a4aa2f13f1f5c
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,6 @@
+**
+!lib
+!public
+!script
+!templates
+!r_v_vote.conf
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..0f160fe8fe200d7845b20ff716198e131a45fc5f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+_work
+docker-compose.yaml
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 9b09b14e7f6cf4f3b4bde6488fc6d4271a7f10d8..6e89260ba92adabe1cb90bb33d4dd86fec5af834 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,11 +1,10 @@
-image: docker:19.03.1
+image: docker:20.10.9
 
 variables:
   DOCKER_TLS_CERTDIR: "/certs"
-  IMAGE_TAG: $CI_REGISTRY_IMAGE:latest
 
 services:
-  - docker:19.03.1-dind
+  - docker:20.10.9-dind
 
 before_script:
   - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
@@ -13,5 +12,8 @@ before_script:
 build:
   stage: build
   script:
-    - docker build -t $IMAGE_TAG .
-    - docker push $IMAGE_TAG
+    - VERSION=`cat VERSION`
+    - docker pull $CI_REGISTRY_IMAGE:latest || true
+    - docker build --cache-from $CI_REGISTRY_IMAGE:latest --tag $CI_REGISTRY_IMAGE:$VERSION --tag $CI_REGISTRY_IMAGE:latest .
+    - docker push $CI_REGISTRY_IMAGE:$VERSION
+    - docker push $CI_REGISTRY_IMAGE:latest
diff --git a/Dockerfile b/Dockerfile
index 16ec60124e212874e21d7aa22d615db851eb1126..ce5d963e2bbefcd5bfa9dbf32720f3b39f6cf9c0 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,7 +1,21 @@
-FROM docker-registry.pirati.cz/ramaseuski/docker-mojolicious 
+FROM alpine:latest
+
+RUN apk update && apk add \
+    wget \
+    make \
+    gcc \
+    perl-dev \
+    perl-mojolicious \
+    perl-json \
+    perl-yaml \
+    perl-io-socket-ssl \
+  	perl-app-cpanminus
+
+RUN cpanm GraphQL::Client
 
 ADD . /opt/rvvote
 
+USER daemon
 EXPOSE 3000
 WORKDIR /opt/rvvote
 CMD ./script/rvvote daemon
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000000000000000000000000000000000000..9084fa2f716a7117829f3f32a5f4cef400e02903
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+1.1.0
diff --git a/lib/RVVote/Chobotnice.pm b/lib/RVVote/Chobotnice.pm
new file mode 100644
index 0000000000000000000000000000000000000000..d4026c20f3480e9600d5601163ffd14938dba572
--- /dev/null
+++ b/lib/RVVote/Chobotnice.pm
@@ -0,0 +1,63 @@
+package RVVote::Chobotnice;
+
+use strict;
+use warnings;
+use utf8;
+use GraphQL::Client;
+use YAML;
+
+our $VERSION = '0.01';
+
+sub new {
+    my $classname = shift;
+    my $url  = shift;
+    my $self = {};
+
+    $self->{client} = GraphQL::Client->new(url => $url);
+
+    bless ($self, $classname);
+    return $self;
+}
+
+sub client {
+    my $self = shift;
+    return $self->{client};
+}
+
+sub get_group_members {
+    my $self     = shift;
+    my $group_id = shift;
+
+    my $query = qq[
+        query MyQuery {
+            group(id: "$group_id") {
+                memberships {
+                    person {
+                        username
+                        displayName
+                        officialLastName
+                    }
+                }
+            }
+        }
+    ];
+
+    my $res = $self->client->execute($query);
+    return undef if $res->{errors};
+    return undef if ! $res->{data};
+
+    my @members = ();
+
+    MEMBER:
+    foreach my $member ( @{ $res->{data}{group}{memberships} } ) {
+        push @members, {
+            fullname => $member->{person}{displayName},
+            user_id  => lc($member->{person}{username}),
+            lastname => $member->{person}{officialLastName},
+        };
+    }
+
+    return sort { $a->{lastname} cmp $b->{lastname} } @members;
+}
+
+1;
diff --git a/lib/RVVote/Controller/RV.pm b/lib/RVVote/Controller/RV.pm
index c1def3a9ba53ff88c0f1b8589c679fa374e137e1..95022c0744aa1535bf6d8e37329261801652b592 100644
--- a/lib/RVVote/Controller/RV.pm
+++ b/lib/RVVote/Controller/RV.pm
@@ -1,6 +1,7 @@
 package RVVote::Controller::RV;
 use Mojo::Base 'Mojolicious::Controller';
-use RVVote::GraphAPI;
+use RVVote::IAPI;
+use RVVote::Chobotnice;
 use MIME::Base64 qw(decode_base64url);
 use JSON;
 
@@ -11,7 +12,7 @@ sub index {
 
 sub members {
     my $c = shift;
-   
+
     my @members = ();
 
     if ($c->param('election')) {
@@ -25,11 +26,17 @@ sub members {
                 }
             } @{ $election }
         };
-    } 
+    }
 
     if ( ! scalar @members ) {
-        my $gapi = RVVote::GraphAPI->new($c->config->{graph_api}{url});
-        @members = $gapi->get_group_members($c->config->{graph_api}{rv_gid});
+        if ( $ENV{USERS_BACKEND} eq 'iapi' ) {
+            my $iapi = RVVote::IAPI->new($c->config->{iapi}{url});
+            @members = $iapi->get_group_members($c->config->{iapi}{rv_gid});
+        }
+        elsif ( $ENV{USERS_BACKEND} eq 'chobotnice' ) {
+            my $chobotnice = RVVote::Chobotnice->new($c->config->{chobotnice}{url});
+            @members = $chobotnice->get_group_members($c->config->{chobotnice}{rv_gid});
+        }
     }
 
     $c->render( json => \@members );
diff --git a/lib/RVVote/GraphAPI.pm b/lib/RVVote/IAPI.pm
similarity index 51%
rename from lib/RVVote/GraphAPI.pm
rename to lib/RVVote/IAPI.pm
index 7c3a95f8eab042b09b261b329a619d0d6a72b49b..5ec4ef1a895770c0da98483b0cdf1c96dfa99326 100644
--- a/lib/RVVote/GraphAPI.pm
+++ b/lib/RVVote/IAPI.pm
@@ -1,4 +1,4 @@
-package RVVote::GraphAPI;
+package RVVote::IAPI;
 
 use strict;
 use warnings;
@@ -28,32 +28,27 @@ sub get_group_members {
     my $self     = shift;
     my $group_id = shift;
 
-    my $res = $self->ua->get( join '/', (
-        $self->{base_url},
-        $group_id,
-        'members'
-    ))->result();
+    my $res = $self->ua->get(
+        sprintf($self->{base_url}, $group_id)
+    )->result();
 
-    return undef if ! $res->is_success;    
+    return undef if ! $res->is_success;
     return undef if ! ref $res->json eq 'ARRAY';
 
     my @members = ();
 
     MEMBER:
     foreach my $member ( @{ $res->json } ) {
-        my $res2 = $self->ua->get( join '/', (
-            $self->{base_url},
-            'user',
-            $member->{username_clean},
-        ))->result();
-        next MEMBER if ! $res2->is_success;    
-        next MEMBER if ! ref $res2->json eq 'ARRAY';
-
-        $member = $res2->json;
-        (undef, $member->{lastname}) = split /\./, $member->{username_clean};
-        push @members, $member;
+        my (undef, $lastname) = split /\s+/, $member->{displayname};
+        push @members, {
+            fullname => $member->{displayname},
+            user_id  => $member->{username},
+            lastname => $lastname,
+        };
     }
 
     return sort { $a->{lastname} cmp $b->{lastname} } @members;
 
-};
+}
+
+1;
diff --git a/r_v_vote.conf b/r_v_vote.conf
index 06fca89fc0956c14c11ca88ac9beead80b217fb5..d264665a3cee077bf390941df7f9e40403476997 100644
--- a/r_v_vote.conf
+++ b/r_v_vote.conf
@@ -1,7 +1,11 @@
 {
     secrets       => ['ac605478557638569200e0e5333891c04929159a'],
-    graph_api => {
-        url     => 'https://graph.pirati.cz', 
-        rv_gid  => 'deadbeef-babe-f002-000000000404', 
-    }
+    iapi => {
+        url    => 'https://iapi.pirati.cz/v1/groups/%d/members',
+        rv_gid => 404,
+    },
+    chobotnice => {
+        url    => 'https://chobotnice.pirati.cz/graphql/',
+        rv_gid => 'R3JvdXBUeXBlOjUzMg==',
+    },
 }
diff --git a/templates/rv_form.html.ep b/templates/rv_form.html.ep
index 5a326b51f6ef3e203ee892541b04537fa4636bc8..374b599b1a2cacd47c3377b1cdf62898383f5a7f 100644
--- a/templates/rv_form.html.ep
+++ b/templates/rv_form.html.ep
@@ -32,15 +32,15 @@ function evaluate() {
     var a = $('form').serializeArray();
     $.each(a, function() {
         var id = this.name.split('_');
-        bills.push({ 
-            "id": id[1], 
-            "value": this.value, 
-            "voter": $('input[name='+this.name+']').attr('data-fullname'),
+        bills.push({
+            "id": id[1],
+            "value": this.value,
+            "voter": $('input[name="'+this.name+'"]').attr('data-fullname'),
         });
     });
 
     $.ajax({
-        url: '/api/calculate/',                 
+        url: '/api/calculate/',
         data: JSON.stringify(bills),
         contentType: 'application/json',
         type: "POST",