Giter Club home page Giter Club logo

ansible-freeipa-server's Introduction

freeipa_server

This role is installing and configuring the FreeIPA Server according to your needs.

This playbook is taking care of the initialisation of the Kerberos admin user (username: admin, passeword is the one which you're setting in freeipa_server_admin_password).

In combination with freeipa (Github) it's possible (and tested) to use freeipa_server with the latest version of FreeIPA itself on Ubuntu >= 18.04 (take a look at the example section).

Don`t support Ubuntu 20.04

Ubuntu 20.04 don`t have pacakge freeipa-server

Requirements

This role requires Ansible 2.5.0 or higher.

You can simply use pip to install (and define) a stable version:

pip install ansible==2.7.7

All platform requirements are listed in the metadata file.

Install

ansible-galaxy install timorunge.freeipa_server

Role Variables

It is required to set the following variables in order to get this role up and running (without customisation). Those variables don't have any default values:

# Admin user kerberos password - at least 8 characters
# Type: Str
freeipa_server_admin_password: Passw0rd
# Primary DNS domain of the IPA deployment
# Type: Str
freeipa_server_domain: example.com
# Directory Manager password - at least 8 characters
# Type: Str
freeipa_server_ds_password: Passw0rd
# The hostname of this machine (FQDN)
# Type: Str
freeipa_server_fqdn: ipa.example.com
# Master Server IP Address
# Type: Str
freeipa_server_ip: 172.20.0.2
# Kerberos realm name of the IPA deployment
# Type: Str
freeipa_server_realm: EXAMPLE.COM

The variables that can be passed to this role and a brief description about them are as follows. (For all variables, take a look at defaults/main.yml)

# Enable/Disable manage RedHat epel repository
# Type: Bool
freeipa_server_enable_epel_repo: true

# Automatically setting an entry in /etc/hosts
# Type: Bool
freeipa_server_manage_host: true

# Choice FreeIPA server installation type (master/replica)
# Type: Str
freeipa_server_type: master

# FQDN of the master FreeIPA server
# Type: Str
freeipa_server_master_fqdn: ''

# The base command for the FreeIPA installation
# Type: Str
freeipa_server_install_base_command: ipa-{{ 'server' if freeipa_server_type == 'master' else 'replica' }}-install --unattended {{ '--server=' + freeipa_server_master_fqdn if freeipa_server_type == 'replica' }}

# The default FreeIPA installation options
# Type: List
freeipa_server_install_options:
  - "--realm={{ freeipa_server_realm }}"
  - "--domain={{ freeipa_server_domain }}"
  - "--setup-dns"
  - "--ds-password={{ freeipa_server_ds_password }}"
  - "--admin-password={{ freeipa_server_admin_password }}"
  - "--mkhomedir"
  - "--hostname={{ freeipa_server_fqdn | default(ansible_fqdn) }}"
  - "--ip-address={{ freeipa_server_ip }}"
  - "--no-host-dns"
  - "--no-ntp"
  - "--idstart=5000"
  - "--ssh-trust-dns"
  - "--forwarder=8.8.8.8"
  - "--auto-forwarders"

Examples

To keep the document lean the install options are stripped. You can find the install options either in this document or in the online man pages for ipa-server-install.

1) Install the FreeIPA server as master with default settings

- hosts: freeipa-server
  vars:
    freeipa_server_admin_password: Passw0rd
    freeipa_server_domain: example.com
    freeipa_server_ds_password: Passw0rd
    freeipa_server_fqdn: ipa-master.example.com
    freeipa_server_ip: 172.20.0.2
    freeipa_server_realm: EXAMPLE.COM
  roles:
    - timorunge.freeipa_server

2) Install the FreeIPA server as replica with default settings

- hosts: freeipa-server
  vars:
    freeipa_server_type: replica
    freeipa_server_master_fqdn: ipa-master.example.com
    freeipa_server_admin_password: Passw0rd
    freeipa_server_domain: example.com
    freeipa_server_ds_password: Passw0rd
    freeipa_server_fqdn: ipa-replica.example.com
    freeipa_server_ip: 172.20.0.3
    freeipa_server_realm: EXAMPLE.COM
  roles:
    - timorunge.freeipa_server

3) Install the FreeIPA server and enable it automatically on all (IPv4) network interfaces

You should still set freeipa_server_ip if you want to use freeipa_server_manage_host.

- hosts: freeipa-server
  vars:
    freeipa_server_admin_password: Passw0rd
    freeipa_server_domain: example.com
    freeipa_server_ds_password: Passw0rd
    freeipa_server_fqdn: ipa.example.com
    freeipa_server_ip: 172.20.0.3
    freeipa_server_realm: EXAMPLE.COM
    freeipa_server_install_options:
      - "--ip-address={{ ansible_all_ipv4_addresses | join(' --ip-address=') }}"
  roles:
    - timorunge.freeipa_server

4) Install the FreeIPA server with custom install options

- hosts: freeipa-server
  vars:
    freeipa_server_admin_password: Passw0rd
    freeipa_server_domain: example.com
    freeipa_server_ds_password: Passw0rd
    freeipa_server_fqdn: ipa.example.com
    freeipa_server_ip: 172.20.0.2
    freeipa_server_realm: EXAMPLE.COM
    freeipa_server_install_options:
      - "--realm={{ freeipa_server_realm }}"
      - "--domain={{ freeipa_server_domain }}"
      - "--setup-dns"
      - "--ds-password {{ freeipa_server_ds_password }}"
      - "--admin-password {{ freeipa_server_admin_password }}"
      - "--mkhomedir"
      - "--hostname={{ freeipa_server_fqdn | default(ansible_fqdn) }}"
      - "--ip-address={{ freeipa_server_ip }}"
      - "--ip-address=10.0.0.2"
      - "--ip-address=192.168.20.2"
      - "--no-host-dns"
      - "--no-ntp"
      - "--idstart=5000"
      - "--ssh-trust-dns"
      - "--forwarder=8.8.8.8"
      - "--auto-forwarders"
      - "--no-ui-redirect"
      - "--no-ssh"
      - "--no-sshd"
  roles:
    - timorunge.freeipa_server

FreeIPA server install options

An overview of the install options for ipa-server-install (4.6.4).

Usage: ipa-server-install [options]

Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  -U, --unattended      unattended (un)installation never prompts the user
  --uninstall           uninstall an existing installation. The uninstall can
                        be run with --unattended option

  Basic options:
    -p DM_PASSWORD, --ds-password=DM_PASSWORD
                        Directory Manager password
    -a ADMIN_PASSWORD, --admin-password=ADMIN_PASSWORD
                        admin user kerberos password
    --ip-address=IP_ADDRESS
                        Master Server IP Address. This option can be used
                        multiple times
    -n DOMAIN_NAME, --domain=DOMAIN_NAME
                        primary DNS domain of the IPA deployment (not
                        necessarily related to the current hostname)
    -r REALM_NAME, --realm=REALM_NAME
                        Kerberos realm name of the IPA deployment (typically
                        an upper-cased name of the primary DNS domain)
    --hostname=HOST_NAME
                        fully qualified name of this host
    --ca-cert-file=FILE
                        File containing CA certificates for the service
                        certificate files
    --no-host-dns       Do not use DNS for hostname lookup during installation

  Server options:
    --setup-adtrust     configure AD trust capability
    --setup-kra         configure a dogtag KRA
    --setup-dns         configure bind with our zone
    --idstart=IDSTART   The starting value for the IDs range (default random)
    --idmax=IDMAX       The max value for the IDs range (default:
                        idstart+199999)
    --no-hbac-allow     Don't install allow_all HBAC rule
    --no-pkinit         disables pkinit setup steps
    --no-ui-redirect    Do not automatically redirect to the Web UI
    --dirsrv-config-file=FILE
                        The path to LDIF file that will be used to modify
                        configuration of dse.ldif during installation of the
                        directory server instance

  SSL certificate options:
    --dirsrv-cert-file=FILE
                        File containing the Directory Server SSL certificate
                        and private key
    --http-cert-file=FILE
                        File containing the Apache Server SSL certificate and
                        private key
    --pkinit-cert-file=FILE
                        File containing the Kerberos KDC SSL certificate and
                        private key
    --dirsrv-pin=PIN    The password to unlock the Directory Server private
                        key
    --http-pin=PIN      The password to unlock the Apache Server private key
    --pkinit-pin=PIN    The password to unlock the Kerberos KDC private key
    --dirsrv-cert-name=NAME
                        Name of the Directory Server SSL certificate to
                        install
    --http-cert-name=NAME
                        Name of the Apache Server SSL certificate to install
    --pkinit-cert-name=NAME
                        Name of the Kerberos KDC SSL certificate to install

  Client options:
    --mkhomedir         create home directories for users on their first login
    -N, --no-ntp        do not configure ntp
    --ssh-trust-dns     configure OpenSSH client to trust DNS SSHFP records
    --no-ssh            do not configure OpenSSH client
    --no-sshd           do not configure OpenSSH server
    --no-dns-sshfp      do not automatically create DNS SSHFP records

  Certificate system options:
    --external-ca       Generate a CSR for the IPA CA certificate to be signed
                        by an external CA
    --external-ca-type={generic,ms-cs}
                        Type of the external CA
    --external-ca-profile=EXTERNAL_CA_PROFILE
                        Specify the certificate profile/template to use at the
                        external CA
    --external-cert-file=FILE
                        File containing the IPA CA certificate and the
                        external CA certificate chain
    --subject-base=SUBJECT_BASE
                        The certificate subject base (default O=<realm-name>).
                        RDNs are in LDAP order (most specific RDN first).
    --ca-subject=CA_SUBJECT
                        The CA certificate subject DN (default CN=Certificate
                        Authority,O=<realm-name>). RDNs are in LDAP order
                        (most specific RDN first).
    --ca-signing-algorithm={SHA1withRSA,SHA256withRSA,SHA512withRSA}
                        Signing algorithm of the IPA CA certificate

  DNS options:
    --allow-zone-overlap
                        Create DNS zone even if it already exists
    --reverse-zone=REVERSE_ZONE
                        The reverse DNS zone to use. This option can be used
                        multiple times
    --no-reverse        Do not create new reverse DNS zone
    --auto-reverse      Create necessary reverse zones
    --zonemgr=ZONEMGR   DNS zone manager e-mail address. Defaults to
                        hostmaster@DOMAIN
    --forwarder=FORWARDERS
                        Add a DNS forwarder. This option can be used multiple
                        times
    --no-forwarders     Do not add any DNS forwarders, use root servers
                        instead
    --auto-forwarders   Use DNS forwarders configured in /etc/resolv.conf
    --forward-policy={first,only}
                        DNS forwarding policy for global forwarders
    --no-dnssec-validation
                        Disable DNSSEC validation

  AD trust options:
    --enable-compat     Enable support for trusted domains for old clients
    --netbios-name=NETBIOS_NAME
                        NetBIOS name of the IPA domain
    --rid-base=RID_BASE
                        Start value for mapping UIDs and GIDs to RIDs
    --secondary-rid-base=SECONDARY_RID_BASE
                        Start value of the secondary range for mapping UIDs
                        and GIDs to RIDs

  Uninstall options:
    --ignore-topology-disconnect
                        do not check whether server uninstall disconnects the
                        topology (domain level 1+)
    --ignore-last-of-role
                        do not check whether server uninstall removes last
                        CA/DNS server or DNSSec master (domain level 1+)

  Logging and output options:
    -v, --verbose       print debugging information
    -d, --debug         alias for --verbose (deprecated)
    -q, --quiet         output only errors
    --log-file=FILE     log to the given file

Testing

Build Status

Testing is done with Vagrant (installing Vagrant) which brings up the following virtual machines:

  • EL
    • 7
  • Fedora
    • 26
    • 27
  • Ubuntu
    • 16.04 LTS (Xenial Xerus)
    • 17.10 (Artful Aardvark)
    • 18.04 LTS (Bionic Beaver)

The latest stable release of Ansible is installed on all virtual machines and is applying a test playbook locally.

For further details and additional checks take a look at the Vagrant entrypoint.

# Testing in all available vagrant machines:
# This will take some time. Grab a coffee. Or two. Or forty two.
cd tests
vagrant up --parallel && vagrant halt
for h in $(vagrant global-status --prune | grep freeipa_server | awk '{print $2}') ; do echo ${h} ; vagrant up --provision ${h} ; vagrant ssh ${h} -c "sudo /vagrant/vagrant-entrypoint.sh" && (echo "$(date): ${h}: pass" >> tests/results.log) || (echo "$(date): ${h}: fail" >> tests/results.log) ; vagrant halt ${h} ; done
vagrant destroy -f

If Vagrant is failing to mount the directories you should ensure that you've installed the VirtualBox Guest Additions.

Travis tests are done with Docker and docker_test_runner. Tests on Travis are performing linting and syntax checks.

For further details and additional checks take a look at the docker_test_runner configuration and the Docker entrypoint.

# Testing locally:
curl https://raw.githubusercontent.com/timorunge/docker-test-runner/master/install.sh | sh
./docker_test_runner.py -f tests/docker_test_runner.yml

Security

This playbook is not taking care of securing FreeIPA Server which can be done with e.g. firewalld or iptables.

Depending on your setup you have to open the following ports:

TCP ports:

  • 80, 443: HTTP/HTTPS
  • 389, 636: LDAP/LDAPS
  • 88, 464: kerberos
  • 53: bind

UDP Ports:

  • 88, 464: kerberos
  • 53: bind

Backup

Be sure to back up the CA certificates stored in /root/cacert.p12. These files are required to create replicas. The password for these files is the Directory Manager (freeipa_server_ds_password) password.

On FreeIPA you can also find a general Backup and Restore page which is covering the most important topics.

There is an Ansible role out there which is doing some basic backups: FreeIPA Server Backup (Github Repo).

Dependencies

None

License

BSD 3-Clause "New" or "Revised" License

Author Information

  • Timo Runge

ansible-freeipa-server's People

Contributors

fgierlinger avatar memberit avatar patsevanton avatar stdevel avatar timorunge avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

ansible-freeipa-server's Issues

ansible version compare fails

Tasks Install FreeIPA server dependency packages and Install FreeIPA server packages fail with

Version comparison: '<' not supported between instances of 'str' and 'int'

Using ansible_version.string instead of ansible_version fixes this.

If you like, I can make a PR

Ansible version: 2.9.13

Task fails

Can't install server, it seems to fail at setting the name:

fatal: [keymaster]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: float object has no element 0\n\nThe error appears to have been in '/Users/till/.ansible/roles/timorunge.freeipa_server/tasks/dependencies.yml': line 8, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n  when: freeipa_server_manage_host\n- name: Add FreeIPA host entry\n  ^ here\n"}

Python PIP is missing

By default, PIP is not installed on EL7 and therefore the role fails:

    TASK [timorunge.freeipa_server : Install FreeIPA server pip dependencies] ******
    FAILED - RETRYING: Install FreeIPA server pip dependencies (3 retries left).
    FAILED - RETRYING: Install FreeIPA server pip dependencies (2 retries left).
    FAILED - RETRYING: Install FreeIPA server pip dependencies (1 retries left).
fatal: [centos-7]: FAILED! => {"attempts": 3, "changed": false, "msg": "Unable to find any of pip2, pip to use.  pip needs to be installed."}

My suggestion is to add python2-pip to vars/RedHat.yml as Python 2.x is the system-wide default for EL7, Fedora 27 and 28.

I created the PR #9 for this.

error in dnspython setup command: Invalid environment marker: python_full_version >= "3.6.2"

Hello!
Thanks for role!
I try install freeipa to CentOS 7

Playbook

  - hosts: freeipa
    become: true
    roles:
      - timorunge.freeipa_server

Inventory

all:
  children:
    freeipa:
      hosts:
        "freeipa":
          ansible_host: "xxxxx"
  vars:
    ansible_user:  centos

Error

TASK [timorunge.freeipa_server : Install FreeIPA server pip dependencies] **************************************************************************************************************
Wednesday 30 March 2022  11:57:22 +0600 (0:03:01.297)       0:03:53.988 *******
FAILED - RETRYING: [freeipa]: Install FreeIPA server pip dependencies (3 retries left).
FAILED - RETRYING: [freeipa]: Install FreeIPA server pip dependencies (2 retries left).
FAILED - RETRYING: [freeipa]: Install FreeIPA server pip dependencies (1 retries left).
fatal: [freeipa]: FAILED! => changed=false
  attempts: 3
  cmd:
  - /bin/pip2
  - install
  - custodia
  - ipapython
  - jwcrypto
  - pyasn1-modules
  - pyopenssl
  - python-ldap
  msg: |-
    stdout: Requirement already satisfied (use --upgrade to upgrade): custodia in /usr/lib/python2.7/site-packages
    Requirement already satisfied (use --upgrade to upgrade): ipapython in /usr/lib/python2.7/site-packages
    Requirement already satisfied (use --upgrade to upgrade): jwcrypto in /usr/lib/python2.7/site-packages
    Requirement already satisfied (use --upgrade to upgrade): pyasn1-modules in /usr/lib/python2.7/site-packages
    Collecting pyopenssl
      Using cached https://files.pythonhosted.org/packages/d5/9f/9c0e3288b85f907a008f9d31318b0e4de31b2f67724a8745e633741f609c/pyOpenSSL-22.0.0-py2.py3-none-any.whl
    Requirement already satisfied (use --upgrade to upgrade): python-ldap in /usr/lib64/python2.7/site-packages
    Requirement already satisfied (use --upgrade to upgrade): cryptography in /usr/lib64/python2.7/site-packages (from custodia)
    Requirement already satisfied (use --upgrade to upgrade): six in /usr/lib/python2.7/site-packages (from custodia)
    Requirement already satisfied (use --upgrade to upgrade): requests in /usr/lib/python2.7/site-packages (from custodia)
    Requirement already satisfied (use --upgrade to upgrade): cffi in /usr/lib64/python2.7/site-packages (from ipapython)
    Collecting dnspython>=1.15 (from ipapython)
      Using cached https://files.pythonhosted.org/packages/99/fb/e7cd35bba24295ad41abfdff30f6b4c271fd6ac70d20132fa503c3e768e0/dnspython-2.2.1.tar.gz
        Complete output from command python setup.py egg_info:
        /usr/lib64/python2.7/distutils/dist.py:267: UserWarning: Unknown distribution option: 'python_requires'
          warnings.warn(msg)
        error in dnspython setup command: Invalid environment marker: python_full_version >= "3.6.2"

        ----------------------------------------

    :stderr: Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-bH8zkw/dnspython/
    You are using pip version 8.1.2, however version 22.0.4 is available.
    You should consider upgrading via the 'pip install --upgrade pip' command.

Not possible to install an ipa replica on an already joined machine as /etc/ipa/default.conf already exists

I would like to install ipa replicas using this role following the guidance here:
https://www.freeipa.org/page/V4/Replica_Setup
which says it should be possible to install a replica on an already joined machine without needing the admin credentials as long as the machine has been added to the ipaservers group already.

The current code does not allow this as the install task is skipped when /etc/ipa/default.conf is already there. It would be good to be able to override this creates check.

Add CA replica option

It would be nice to also have the option to create a CA replica, currently this needs to be done manually by leveraging the ipa-ca-install command.

EPEL GPG key is not added

On systems without installed EPEL GPG key, the role aborts with the following error:

TASK [timorunge.freeipa_server : Install FreeIPA server packages] **************
FAILED - RETRYING: Install FreeIPA server packages (3 retries left).
FAILED - RETRYING: Install FreeIPA server packages (2 retries left).
FAILED - RETRYING: Install FreeIPA server packages (1 retries left).
fatal: [centos-7]: FAILED! => {"attempts": 3, "changed": false, "changes": {"installed": ["bind", "bind-dyndb-ldap", "ipa-server", "ipa-server-common", "ipa-server-dns", "ipa-server-trust-ad"]}, "msg": "\nYou have enabled checking of packages via GPG keys. This is a good thing. \nHowever, you do not have any GPG public keys installed. You need to download\nthe keys for packages you wish to install and install them.\nYou can do that by running the command:\n    rpm --import public.gpg.key\n\n\nAlternatively you can specify the url to the key you would like to use\nfor a repository in the 'gpgkey' option in a repository section and yum \nwill install it for you.\n\nFor more information contact your distribution or package provider.\n\nProblem repository: epel\n", "rc": 1, "results": ["Loaded plugins: fastestmirror\n"]}

To fix this, I suggest adding a task to add the EPEL GPG key before installing the dependency packages. I created the Pull request #7 for this.

After this fix, the playbook proceeded for the CentOS 7 Vagrant box:

TASK [timorunge.freeipa_server : Add EPEL repository] **************************
ok: [centos-7]

TASK [timorunge.freeipa_server : Add EPEL GPG key] *****************************
changed: [centos-7]

TASK [timorunge.freeipa_server : Install FreeIPA server dependency packages] ***
changed: [centos-7]
...

Additional note:
Since the latest release of your Ansible role there were several commits to your master branch. Maybe creating a new release would be a good idea. :)

Python DNS issue stops installer task

If I'm honest I'm not entirely sure that this an issue with the playbook per se but I'm curious if anyone has run into this issue as well.

When running the 'Run the FreeIPA Server installer' task it keeps failing on this error. I've already tried to reinstall the python DNS package both using PIP and source but the issue remains. Does anyone have any idea why this might happen?

" from dns.exception import DNSException", " File \"/usr/lib/python2.7/site-packages/dns/exception.py\", line 141", " raise self.exception_class(str(exc_val)) from exc_val", " ^", "SyntaxError: invalid syntax"

Unable to find any of pip3 to use. pip needs to be installed when use ansible 2.12

Hello! Thanks for role!
I try install and get error

Playbook

  - hosts: freeipa
    become: true
    roles:
      - timorunge.freeipa_server

Inventory

all:
  children:
    freeipa:
      hosts:
        "freeipa":
          ansible_host: "xxxxx"
  vars:
    ansible_user:  ubuntu

Error

TASK [timorunge.freeipa_server : Install FreeIPA server pip dependencies] **************************************************************************************************************
Wednesday 30 March 2022  12:16:51 +0600 (0:03:05.462)       0:04:06.222 *******
FAILED - RETRYING: [freeipa]: Install FreeIPA server pip dependencies (3 retries left).
FAILED - RETRYING: [freeipa]: Install FreeIPA server pip dependencies (2 retries left).
FAILED - RETRYING: [freeipa]: Install FreeIPA server pip dependencies (1 retries left).
fatal: [freeipa]: FAILED! => changed=false
  attempts: 3
  msg: Unable to find any of pip3 to use.  pip needs to be installed.

Version

ansible [core 2.12.2]
  python version = 3.8.10 (default, Nov 26 2021, 20:14:08) [GCC 9.3.0]

Server where ansible

cat /etc/*release*
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.3 LTS"
NAME="Ubuntu"
VERSION="20.04.3 LTS (Focal Fossa)"

Remote server

cat /etc/*release*
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.3 LTS"
NAME="Ubuntu"
VERSION="20.04.3 LTS (Focal Fossa)"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.